JavaScript must be enabled to play.
Browser lacks capabilities required to play.
Upgrade or switch to another browser.
Loading…
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
<<skill setup.BasicStrike 'Strike'>> <<AP 1>> <<append "#fight">> <p> Punching your opponent <<EnDMG 1 8 $cqcmodifier>>. </p> <</append>> <</skill>>
/* Player object (WIP)*/ <<set $netAccess = {aware : false, travel : false}>> <<set $player = { maxHealth: 80, health: 80, shield: 20, block: 0, maxBlock : 3, AP : 3, modif: { }, ondamage: '', inventory: [], equip: [], storage: [], key : 0, infected: false }>> <<set $hasFought = []>> /* Enemies the player has seen, by name */ /* Game variables */ <<set $enGlobal = 100>> /* global enemy damage */ <<set $difficulty = 1>> /* Cheat vars! */ /*<<set $cheat = window.location.hash === '#cheat' ? true : false>>*/ <<set $cheat = true>> <<set $stowCheatMenu = true>> <<set $exp = 0>> /* Experience */ <<set $turn to "Your turn.<br>">> <<set $RR to false>> /* Respawn */ <<set $infected = false>> <<set $AutoAware = false>> /* hasn't met automatons */ <<set $surprise to 0>> /*extra AP when surprise*/ /*Health and shield*/ <<set $shield to 10>> <<set $MaxHealth to 100>> <<set $health to $MaxHealth>> /*Player stats*/ <<set $capacity to 5>> <<set $weaponcapacity = $dronecapacity = 2>> <<set $AP = 3>> /* Action points */ <<set $stealth = 1>> /*odds to surprise enemies*/ <<set $init = 1>> <<set $maxBlock = 3>> <<set $CritChance = 5, $CritMultiplier = 150>> 5% chance for crits, crits deal 150% of damage /* Arrays and inventories */ <<set $storage = $weapons = $drones = $equip = $inventory = []>> /* Charges */ <<set $over = $advover = 0>> /*Overdrive charges*/ <<set $stackover = $advstackover = $rstackover = 0>> /* Stack overflow*/ <<set $missiles = $advmissiles = $wristmissiles = 0>> /*missiles*/ <<set $blast = $advblast = $rblast = 0>> /*concusive blast*/ <<set $HEgrenade = $stungrenade = $acidgrenade = 0>> /* Grenade(weapon)*/ /*Modifiers*/ <<set $regen = 1>> <<set $stunmodifier = 0>> /*odds to stun*/ <<set $extrause = 1>> /*extra uses for limited items, 1=1x */ <<set $blastmodifier = 100>> /*explosives*/ <<set $elecmodifier = 100>> /*electric attacks*/ <<set $cqcmodifier = 100>> /*melee*/ <<set $rangemodifier = 100>> /*ranged*/ <<set $healmodifier = 100>> /*hp healed*/ <<set $DMGresist = 0>> /* Used as percents */ <<set $weaponsmodifier = 100>> /*weapons affinity*/ <<set $allin = 0>> /* odds of extra action */ <<set $heatgain = 0>> /* Heat gain on AP spent, integer*/ <<set $kincharge = 0>> /* Shield restored on AP spent */ <<set $blockGain = 0>> /* Block gained at start of turn */ <<set $droneDMG = $droneaffinity = 100>> <<set $ammosynt = 0>> /* Chance to regain ammo*/ <<set $ammotype to "None">> <<set setup.VarsToClone = ['droneDMG', 'CDrone', 'MDrone', 'HDrone', 'shield', 'DMGresist', 'rangemodifier', 'freemove', 'freeshot']>> <<set setup.VarsWithExtrause = ['missiles', 'advmissiles', 'over', 'advover', 'stackover', 'advstackover', 'rstackover', 'blast', 'advblast', 'rblast', 'HEgrenade', 'stungrenade', 'acidgrenade', 'wristmissiles']>> <<set setup.stats = ['regen', 'stunmodifier', 'weaponsmodifier', 'cqcmodifier', 'rangemodifier', 'blastmodifier', 'elecmodifier', 'allin', 'ammotype', 'healmodifier', 'DMGresist', 'extrause', 'exp', 'capacity', 'weaponcapacity', 'MaxHealth', 'shield', 'kincharge', 'heatgain', 'AP', 'health', 'droneDMG' , 'droneaffinity']>> /* Has items */ <<set $grapple = 0>> /* has a grapple arm, for navigation */ <<set $gunblade = 0>> /*has gun blade*/ <<set $rifle = 0>> /*has rifle*/ <<set $freemove = 0>> /* one free move every turn*/ <<set $freeshot to false>> /* free pistol shot */ /*Economy*/ <<set $scraps to 0>> <<set $money to random(15,35)>> /* Time variables */ <<set $min = 0>> <<set $day to 1>> <<set setup.time to ["night","late night","early morning","morning","early afternoon","afternoon","evening","late evening"]>> /* 9th value is copy of first, solves the undefined $time+1 issue*/ <<set setup.palette = [ [0, 0, 0], [6, 0, 46], [36, 54, 72], [72, 66, 33], [104, 86, 44], [94, 41, 25], [55, 21, 0], [0, 19, 49], [0, 0, 0] ]>> <<set $time = 5>> <<set $color = setup.palette[$time]>> <<set $spotlight = [0,0,0,0], $spotmax = 10>> /* Max grid width based on screen width */ <<set $gridwidth = Math.round(innerWidth/300)>> /* Range names array*/ <<set setup.ranges = ['Close quarters','Short','Medium','Long']>> <<set setup.conditions = ['$rooms[$pos-$MaxX] !== "Obstacle" && $pos > $MaxX-1','$rooms[$pos-$MaxX] !== "Obstacle" && ($pos+1)%$MaxX !== 1','$rooms[$pos-$MaxX] !== "Obstacle" && ($pos+1)%$MaxX','$rooms[$pos-$MaxX] !== "Obstacle" && $pos < $MaxX*$MaxY-$MaxX'], setup.directions = ['_up','_left','_right','_down']>> /* Key binding variables */ <<set settings.keys = { up : 'ArrowUp,w,z', down : 'ArrowDown,s', left : 'ArrowLeft,a,q', right : 'ArrowRight,d', wait : 'x', flee : 'f', yes : 'y', no : 'n' }>> <<set setup.settingSetter = function(setting,rootVar,value){ State.setVar(setting, value); $(':root').css(rootVar, value); Setting.save(); }>> <<set setup.shrinkSkills = function(value,depth) { if (!$('#moveback').visible() && depth > 0) { $(':root').css('--skillSize', (value-1)+'em'); setTimeout(setup.shrinkSkills(value-1,depth-1),200); } }>> <<set $count = 0>> /* For tutorial */ Dismiss splashscreen! <<set setup.dismissSplashScreen = function () { $('#splashpicture').animate({'left' : '-72vw'}, 500); $('#blackscreen, #splashcontainer').addClass('toTransparent'); $('#splashaffix').animate({'right' : '-44vw'}, 500, () => {$('#blackscreen').hide()}); }>> Change active shop tab <<run setup.toggleShop = function(num) { $('.activeBut').removeClass('activeBut'); $('#but'+num).addClass('activeBut'); }>>
/* Turn speed */ <div class='settingBox' data-title='Enemy turn speed'> <<inputbox range 'settings.turnSpeed' min .25 max 3 style 'direction: rtl' step .1 value settings.turnSpeed>> <<onchange>> <<replace '#speed'>><<= settings.turnSpeed>> seconds<</replace>> <</inputbox>> <br> <span id="speed"><<= settings.turnSpeed>> seconds</span> </div> <div style='display: grid; grid-auto-flow: column; margin-bottom: 2em;'> <div class='settingBox' data-title='HP bar style'> <<toggle 'settings.HPdisplay' 'button'>> <<case 'numbers' 'Number values'>> <<case 'bar' 'Health bar'>> <<all>><<trigger 'UIupdate'>> <</toggle>> </div> <div class='settingBox' data-title='Leftbar status'> <<toggle 'settings.stowLeftbar' 'button'>> <<case false 'Always visible.'>> <<case true 'Stowed.'>> <<all>><<run setup.stowLeft()>> <</toggle>> </div> <div class='settingBox' data-title='Saves'> <<but "Save dialog">> <<run UI.saves()>> <</but>> <<if $cheat>> <<but "Unencoded save">> <<run setup.ToDisk()>> <</but>> <</if>> </div> </div> /* Color palette */ <div style='display: grid; grid-template-columns: 1fr 1fr 1fr;'> <div class='settingBox' data-title='HP color'> <<inputbox color 'settings.HPcolor' value settings.HPcolor>> <<onchange>> <<run $(':root').css('--hp', settings.HPcolor)>> <</inputbox>> </div> <div class='settingBox' data-title='Main color'> <<inputbox color 'settings.mainColor' value settings.mainColor>> <<onchange>> <<run $(':root').css('--orange', settings.mainColor)>> <</inputbox>> </div> <div class='settingBox' data-title='Highlight'> <<inputbox color 'settings.mainWhite' value settings.mainWhite>> <<onchange>> <<run $(':root').css('--white', settings.mainWhite)>> <</inputbox>> </div> <div class='settingBox' data-title='Shield color'> <<inputbox color 'settings.shieldColor' value settings.shieldColor>> <<onchange>> <<run $(':root').css('--shield', settings.shieldColor)>> <</inputbox>> </div> <div class='settingBox' data-title='Mess around'> <<hover>> <<a ' Randomize '>> <<run setup.settingSetter('settings.HPcolor','--hp','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.mainColor','--orange','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.mainWhite','--white','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.shieldColor','--shield','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.backColor','--background','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.fontColor','--color','#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)), setup.settingSetter('settings.borderRadius','--radius', randomFloat(0,5)+'em'), setup.settingSetter('settings.borderThickness','--borderThickness', random(1,8)+'px')>> <<rep '.passage'>> <<= Story.get(passage()).processText()>> <</a>> <<tip>>Terrible idea but I can't stop you... <</hover>> <<a 'Back to default'>> <<run setup.settingSetter('settings.HPcolor','--hp','Teal'), setup.settingSetter('settings.mainColor','--orange','DarkOrange'), setup.settingSetter('settings.mainWhite','--white','SeaShell'), setup.settingSetter('settings.shieldColor', '--shield', 'aquamarine'), setup.settingSetter('settings.backColor','--background','#111'), setup.settingSetter('settings.fontColor','--color','SeaShell'), setup.settingSetter('settings.borderRadius','--radius','1em'), setup.settingSetter('settings.borderThickness','--borderThickness', '2px')>> <<rep '.passage'>> <<= Story.get(passage()).processText()>> <</a>> </div> <div class='settingBox' data-title='Background'> <<inputbox color 'settings.backColor' value settings.backColor>> <<onchange>> <<run $(':root').css('--background', settings.backColor)>> <</inputbox>> </div> <div class='settingBox' data-title='Font color'> <<inputbox color 'settings.fontColor' value settings.fontColor>> <<onchange>> <<run $('body').css('color', settings.fontColor)>> <</inputbox>> </div> <div class='settingBox' data-title='Border radius'> <<inputbox range 'settings.borderRadius' min 0 max 5 step .1 value settings.borderRadius>> <<onchange>> <<run $(':root').css('--radius', settings.borderRadius + 'em')>> <</inputbox>> </div> <div class='settingBox' data-title='Border thickness'> <<inputbox range 'settings.borderThickness' min 1 max 8 step 1 value settings.borderThickness>> <<onchange>> <<run $(':root').css('--borderThickness', settings.borderThickness + 'px')>> <</inputbox>> </div> </div> <<but "Toggle fullscreen">> <<run Fullscreen.toggle();>> <</but>> <<but 'About' goto 'about'>><</but>> <<a "Back" goto $prev>><</a>>
<<on 'statChange' 'div' style 'display:inherit'>> <div style='display:flex; justify-content:center;'> <div style='display: grid;align-content: center;'> <h3>WEAPONS</h3> <div @class="$weaponcapacity gte 3 ? 'gridsmall' : 'center'"> <<for _i=0;_i lt $weaponcapacity;_i++>> <<if $weapons[_i]>> <<itemstore $weapons[_i]>> <<else>> <div class="hex"> <div class='slot'></div> </div> <</if>> <</for>> </div> </div> <div style='margin-left:3em;padding-left:3em;display: grid;align-content: center;'> <h3>DRONES</h3> <div @class="$dronecapacity gte 3 ? 'gridsmall' : 'center'"> <<for _i=0;_i lt $dronecapacity;_i++>> <<if $drones[_i]>> <<itemstore $drones[_i]>> <<else>> <div class="hex"> <div class='slot'></div> </div> <</if>> <</for>> </div> </div> </div> <h3>IMPLANTS</h3> <div @class="$capacity gte $gridwidth ? 'grid' : 'center'"> <<for _i=0;_i lt $capacity;_i++>> <<if $equip[_i]>> <<if _i === 0>> <<itemstore $equip[_i]>> <<else>> <<itemstore $equip[_i]>> <</if>> <<else>> <div class="hex"> <div class='slot'></div> </div> <</if>> <</for>> </div> <<if $storage.length>> <h3>STORAGE</h3> <div @class="$storage.length gte $gridwidth ? 'grid' : 'center'"> <<for _item range $storage>> <<itemequip _item>> <</for>> </div> <</if>> <</on>> <<a "Back" goto $prev>> <</a>> <<include 'Stats'>>
Blinding light rains down through the upper levels, from a glass dome far above your head. Sunlight feels nice but also reminds you how deep underground you are. Gotta make descriptions work... Check for empty coords left, $desc not indicated on map place them like the rest of curios, enemies...
<<on 'rangeChange' 'span' id 'moveback'>> <<set _moveClasses = [ (_freemove ? 'free' : '') , (_kinmove ? 'kinmove' : '') , (_ground ? 'ground' : '')]; _moveClasses = _moveClasses.join(' '); _moveInfo = (_ground ? 'Get up' : 'Move back'); _moveIndic = (_range lt 4 || _ground ? 'rangelight' : 'rangedead') + (_freemove ? ' hollow' : '') >> <<a " <img src='https://malifaciousgames.neocities.org/media/backward.png' @class='_moveClasses'> <div class='skillinfo'>_moveInfo</div> <div @class='_moveIndic'/> " key settings.keys.down data-key ⇓ class skillShort >> <<if _AP gt 0 && $enhealth>> <<if _range lt 4 || _ground>> <<set _moveText = (_ground ? 'You jump to your feet' : 'You take a step back') + (_ground && _kinmove ? ' and take a step back.' : '.')>> <<range `(_kinmove? 1 : 0) + (_ground? 0 : 1)`>> <<AP `_freemove ? 0 : 1` 'moveback'>> <<if _freemove>><<set _freemove -->><</if>> <<trigger 'rangeChange'>> <<run $("#fight").wiki('<p>'+_moveText+'</p>')>> <<else>> <<replace "#next">> <div class='warning'> You are already as far as you can be! </div> <</replace>> <</if>> <</if>> <</a>> <</on>>
<<on 'rangeChange' 'span' id 'movefor'>> <<set _moveClasses = (_freemove ? ' free' : '') + (_kinmove ? ' kinmove' : '') + (_ground ? ' ground' : ''); _moveInfo = (_ground ? 'Get up' : 'Move forward'); _moveIndic = (_range gt 1 || _ground ? 'rangelight' : 'rangedead') + (_freemove ? ' hollow' : ''), _moveIcon = setup.locLoad('forward') >> <<a " <img @src=_moveIcon @class='_moveClasses'> <div class='skillinfo'>_moveInfo</div> <div @class='_moveIndic'/> " key settings.keys.up data-key ⇑ class skillTall >> <<if _AP gt 0 && $enhealth>> <<if _range gt 1 || _ground>> <<set _moveText = (_ground ? 'You jump to your feet' : 'You lunge toward your opponent') + (_ground && _kinmove ? ' and lunge toward your opponent.' : '.')>> <<range `(_kinmove? -1 : 0) + (_ground? 0 : -1)`>> <<AP `_freemove ? 0 : 1` 'movefor'>> <<if _freemove>><<set _freemove -->><</if>> <<trigger 'rangeChange'>> <<run $("#fight").wiki('<p>'+_moveText+'</p>')>> <<else>> <<replace "#next">> <div class='warning'> You are already as close as you can be! </div> <</replace>> <</if>> <</if>> <</a>> <</on>>
<<widget "AP">> <<if typeof _args[0] !== 'number'>> <<set _args[0] = eval(parse(_args[0]))>> <</if>> /* Dividers */ <<if _args[1]>> <<divider _args[1]>> <<elseif _args[0] gt 0>> <<divider 'ap'>> <<elseif _args[0] lt 0>> <<divider 'buff'>> <<else>> <<divider 'free'>> <</if>> /* AP spend */ <<set _AP -= _args[0]>> <<set _actionTaken++, _APspent += _args[0]>> /* Update AP counter/status effects*/ <<trigger 'statusUpdate'>> <<set _heat += $heatgain>> <<if $kincharge && _args[0] gt 0>> <<set _shield += $kincharge>> <<trigger 'UIupdate'>> <</if>> /* DoT effects */ <<if _acid gt 0>> <<append "#fight">> <p class='small'>You take <<DMG 1 _acid 'acid' 'noverb'>> from the acid.</p> <</append>> <<set _acid -->> <</if>> /* Animated scroll to bottom, very fancy */ <<run $('#fight').stop().animate({ scrollTop: $('#fight')[0].scrollHeight }, 800); >> /* Trigger enemy turn when AP===0 */ <<if _AP lt 1>> <<timed `settings.turnSpeed/4 + "s"`>> <<EnemyTurn>> <</timed>> <</if>> <</widget>>
<<if _enemyuse && _range gt 1>> <<divider 'buff'>> <p> The slender robot aims down its long-barreled rifle. </p> <<set _buff++, _enemyuse-->> <<elseif _range === 1>> <<if _action === $enemy.AP>> /* At close range on last action */ <<divider 'enemy'>> <p> Your opponent hits you with the stock of its rifle, <<DMG 1 8>>. </p> <<else>> <<divider 'movefor'>> <p> <<= either( 'The robot pushes you back, <<DMG 1 4>>.', 'The robot moves back for a better shot.' )>> </p> <<range 1>> <</if>> <<elseif _range === 2>> <<if $enhealth lt 20 && random(2) === 2>> <<divider 'buff'>> <<set _heal = random(8,15), $enhealth += _heal>> <<trigger 'EnemyUpdate'>> <p> The mechanical marksman takes cover and self repairs for <b class='hp'>_heal</b> health. </p> <<elseif _action === 1>> <<divider 'movefor'>> <p> The robot marksman moves to a better position. </p> <<range 1>> <<else>> <<divider 'enemy'>> <p> The robot takes a quick shot, <<DMG 1 `12 + _buff*4`>>. </p> <</if>> <<else>> <<if $enhealth lt 20 && random(1)>> <<divider 'buff'>> <<set _heal = random(8,15), $enhealth += _heal>> <<trigger 'EnemyUpdate'>> <p> The mechanical marksman takes cover and self repairs for <b class='hp'>_heal</b> health. </p> <<else>> <<divider 'enemy'>> <p> Your opponent shoots you, <<DMG 1 `15 + _buff*5`>>. </p> <</if>> <</if>>
<<run $('body').animate({'opacity':1}, 1300);>> <b class='red'>You have died.</b> <<a "Retry?" goto 'init spin' id 1>> <<run $.wiki('<<include StoryInit>>'), Save.slots.delete(0)>> <</a>>
<<widget "range">> <<set _range += _args[0]>> <<if _range gt 4>> <<set _range = 4>> <<elseif _range lt 1>> <<set _range = 1>> <</if>> /* Moving by any means when down gets you up */ <<if _ground>> <<set _ground = false>> <</if>> /* Global event */ <<done>> <<trigger "rangeChange, skillboxRefresh">> <</done>> /* Divider */ <<set _last = (_args[0] gt 0) ? 'movefor' : 'moveback'>> <</widget>>
<<widget "health">> <<run console.log(_args[0])>> /* Do math if args is supplied */ <<if _args[0] lt 0>> /*negative value AKA damage*/ <<set $health += Math.clamp(_args[0] , -$health , 0)>> <<elseif _args[0] gt 0>> <<set $health += Math.clamp(_args[0] , 0 , $health)>> <</if>> <<if $health gt $MaxHealth>> <<set $health = $MaxHealth>> <</if>> /* Update UI */ <<trigger 'UIupdate'>> <<if passage() === 'Combat' && $health lt 1>> /* Death in combat (most likely)*/ <<set _AP = 0>> <<run $('#next, #enhealth, #CombatUI').empty(); setTimeout(() => { $('#fight').wiki(" <<a '<b>You collapse from your injuries.</b>'>> <<timed .6s>><<goto 'Death'>><</timed>> <<run $('body').animate({'opacity':0}, 600)>> <</a>>"); }, 50)>> <<elseif $health lt 1>> /* Death out of combat*/ <<run $('a, button').ariaDisabled(true)>> <<timed 1s>> <<run $('body').css('visibility','hidden');>> <<goto 'Death'>> <</timed>> <</if>> <</widget>>
<<widget "NewCombatConfig">> /* General inits ----------------------------------------------------*/ /* Set skillsize back to default */ <<run $(':root').css('--skillSize','10em')>> <<set _range = $enemy.startrange ?? random(1,4)>> <<set _turn to 1>> <<set _action = 0, _actionTaken = 0, _APspent = 0>> /* Enemy action counter */ <<set _talk to 1>> /*talk 'token' for the enemy*/ <<set _talked to false>> /*if true, stops enemyturn to give time to read*/ /* Drones */ <<set _activeDrones = []>> <<set _droneturn = 0>> /* Vars to temp */ <<for _i range setup.VarsToClone>> <<= '<<set _'+_i+' = $'+_i+'>>'>> <</for>> /* Charges * extrause to temp */ <<for _i range setup.VarsWithExtrause>> <<= '<<set _'+_i+' = Math.round($'+_i+'*$extrause)>>'>> <</for>> /* Player config*/ <<set _AP = $AP+$surprise, _heat = 100, _ground = _blinded = false, _block = 0, _playerStun = _acid = 0>> /* Duplicate items/weapons sorting! */ <<set _totskills = [setup.BasicStrike]>> <<for _item range $equip>> <<if _item.type !== "passive" && _item.type !== "ammo">> <<set _totskills.pushUnique(_item)>> <</if>> <</for>> <<for _item range $weapons>> <<set _totskills.pushUnique(_item)>> <</for>> <<for _item range $drones>> <<set _totskills.pushUnique(_item)>> <</for>> /* Enemy config -----------------------------------------------------*/ <<set $enhealth = $MaxEnhealth>> /* Enemies regen on page refresh */ <<set _aim to false>> /* riflebot aim */ <<set _enfled = false>> <<set _buff = 0>> /* in combat buffs for the enemy */ <<set _enemyuse to 1>> /*enemy single use skills*/ /* DoT object */ <<set $enemy.DoT = {darts : 0, acid : 0, somethingElse : 0}>> /* Enemy statuses */ <<set _darts to 0>> <<set _enstun to 0>> <<set _enemyAP = $enemy.AP, _enGlobal = $enGlobal>> <<set $enemy.block = 0; $enemy.DMGresist = ($enemy.DMGresist ?? 0); $enemy.plating = ($enemy.plating ?? 0); >> <<done>> <<triggerEffect 'oninit'>> <</done>> <</widget>>
<<if !tags().includesAny('combat','Menu','initscreen','noback')>> <<set $prev = passage()>> <</if>> <<set _id = 0>> <<if !tags().includes('Menu') && !tags(previous()).includes('Menu')>> <<time `random(3,6)`>> <</if>>
<<if _range gt 1 and _action is 3>> <<divider 'enemy'>> <p> The machine shoots at you with an arm-mounted machinegun <<DMG 2 5>>. </p> <<elseif _range gt 1>> <<divider 'movefor'>> <<range -1>> <p> The monstrous machine charges you <<if _range == 1>> and slams you with its shoulder, <<DMG 1 10>>. <<else>>.<</if>> </p> <<elseif !_ground>> <<divider 'enemy'>> <p> The enemy throws you to the ground, <<DMG 1 15>>. </p> <<set _ground = true>> <<else>> <<divider 'enemy'>> <p> <<= either("The robot punches you with incredible strength, <<DMG 1 18>>.","The robot showers you with blows, <<DMG 2 10>>.")>> </p> <</if>>
<<if !(_turn % 3) && $enhealth !== $enemy.health && !$enemy.block>> <<divider 'buff'>> <p> The damaged sentry retracts behind its hardened shield. </p> <<set $enemy.block = 8>> <<trigger 'EnemyUpdate'>> <<elseif $enemy.block && $enhealth === $MaxEnhealth>> <<divider 'enemy'>> <p> The sentry unfolds, fully healed. </p> <<set $enemy.block = 0>> <<trigger 'EnemyUpdate'>> <<elseif $enemy.block>> <<divider 'buff'>> <p> The sentry is immobile behind its shield. <br> A mechanical buzz can be heard from inside the metal shell. </p> <<set $enhealth += 6, $enemy.block--, _sbheal = true>> <<if $enhealth gt $enemy.health>> <<set $enhealth = $enemy.health>> <</if>> <<trigger 'EnemyUpdate'>> <<elseif !$enemy.block && _sbheal>> <<divider 'enemy'>> <p> The sentry unfolds once more. </p> <<set _sbheal = false>> <<elseif _range === 1>> <<divider 'moveback'>> <p> The sentry releases a blast from its body, <<DMG 1 12>>, pushing you back. </p> <<range 1>> <<elseif _action === 3>> <<divider 'buff'>> <p> Mechanical clicking can be heard as the turret adjusts its aim. </p> <<set _buff ++>> <<else>> <<divider 'enemy'>> <p> The robot showers you in hot lead, <<switch _range>> <<case 2>><<DMG 2 `8+_buff`>> <<case 3>><<DMG 2 `7+_buff`>> <<case 4>><<DMG 2 `6+_buff`>> <</switch>>. </p> <</if>>
<p> You make out the squat and rounded silhouette of an insect, the size of a dog. <br> It seems aggressive. </p> <<a 'Fight it!' id 1 goto 'Combat'>> <<fight setup.CyberBug 'rand'>> <</a>>
<<if $enhealth lt 10>>/* Hp - get away */ <<if _range === 4>> <<divider 'movefor'>> <p> The damaged insect <<= either('disappears in the shadows','manages to flee')>>. </p> <<set _vic = true>> <<Victory>> <<else>> <<divider 'movefor'>> <p> The mechanical insect <<= either('tries to flee','scuttles back')>>. </p> <<range 1>> <</if>> <<elseif $enhealth lt 25>> /* Mid hp - stay at range */ <<if _range gt 2>> <<divider 'moveback'>> <p> The mechanical bug advances toward you. </p> <<range -1>> <<elseif _range === 2>> <<divider 'enemy'>> <p> The bug spits <b class='acid'>acid</b> at you, <<DMG 1 3 'acid'>>. </p> <<if !_acid>> <img src='https://malifaciousgames.neocities.org/media/acidspit.png'> <</if>> <<set _acid += 2>> <<elseif _range === 1 && _action === 1>> <<divider 'movefor'>> <p> The insect <<= either('scuttles back','puts distance between you')>>. </p> <<range 1>> <<else>> /* High hp - rush and chomp */ <<divider 'enemy'>> <p> The damaged bug bites you, <<DMG 1 5>>. </p> <</if>> <<else>> <<if _range gt 1>> <<divider 'moveback'>> <p> The mechanical insect rushes toward you <<= _action === 1? 'with a sharp screech':''>>. </p> <<range -1>> <<elseif _turn%2 && _action === 1>> <<divider 'enemy'>> <p> The insect spits acid straight to your face, <<DMG 1 6 'acid'>>. <<set _acid += 4>> </p> <<else>> <<divider 'enemy'>> <p> <<= either("The cyber bug bites you <<DMG 1 7>>.","The cyber bug rends you with its claws, <<DMG 2 4>>.")>> </p> <</if>> <</if>>
<<a " <img src ='https://cdn.discordapp.com/attachments/949715863479672913/1014617442703642745/waitwip.png'> <div class='skillinfo'>Wait for 1 AP</div>" key settings.keys.wait data-key settings.keys.wait class skillTall>> <<if _AP>> <<AP 1>> <<run $("#fight").wiki("<p>You wait for your enemy's next move.</p>")>> <</if>> <</a>>
<<widget "EnemyTurn">> <<if $enhealth && $health>> /* Cannot clear the death/victory message */ /* ---------------------------- Init ------------------------------- */ <<run _blinded = false, _droneturn = _playerStun = 0, _heat = 100; /* Update display*/ $('#next').empty(); $('#fight').wiki('<h3>Enemy turn</h3>'); $('#CombatUI').hide(); >> /* ---------------------------- Loop ------------------------------- */ <<repeat `settings.turnSpeed+"s"`>> <<if !$enhealth || !$health || _vic>> /* Player or enemy has died */ <<stop>> <<elseif _talked>> <<set _talked = false>> <<stop>> <<elseif _enemyAP gt 0>> /* --------------------------- Action ------------------------------ */ <<run _enemyAP --, _action ++; $('#fight').stop().animate({ scrollTop: $('#fight')[0].scrollHeight}, 800);>> /* Enemy is stunned */ <<if _enstun>> <<run _enstun --; $('#fight').wiki(" <<divider 'stun'>> <p>The enemy is stunned.</p> ")>> <<else>> <<run $('#fight').wiki('<<include $enemy.behav>>')>> <</if>> /* DoT after enemy action */ <<append '#fight'>> <<include 'EnDoT'>> <</append>> <<elseif _droneturn lt _activeDrones.length>> /* -------------------------- Drone Turn --------------------------- */ <<if _droneturn === 0>> <<append "#fight">><h3>DRONES</h3><</append>> <</if>> <<set _currentDrone = _activeDrones[_droneturn]>> /* Highlight effect */ <<run $('#drone'+_droneturn).addClass('active'), $('#drone'+(_droneturn-1)).removeClass('active')>> <<append '#fight'>> <<include _currentDrone.action>> <</append>> <<set _droneturn ++>> <<run $('#fight').stop().animate({ scrollTop: $('#fight')[0].scrollHeight }, 800);>> <<elseif !_vic>> /* No AP, no drones, no victory -> next turn! */ /* ------------------------- Turn reset ---------------------------- */ /* Reset stats to default! */ <<set _aim = false, _enemyAP = $enemy.AP, _DMGresist = $DMGresist, _rangemodifier = $rangemodifier, _droneDMG = $droneDMG, _action = 0, _AP = $AP, _turn ++, _freeshot = $freeshot, _freemove = $freemove>> <<run $('#CombatUI').css('display','grid'); $('#fight').wiki('<h3>TURN _turn</h3>'); >> <<include 'ammosynt'>> <<trigger 'statusUpdate, rangeChange, skillboxRefresh, droneRefresh'>> /* Drone refresh removes highlight */ <<append '#fight'>> <<if $blockGain && _block lt $maxBlock>> <p>Gained $blockGain block.</p> <<set _block = Math.clamp(_block+$blockGain, 0, $maxBlock)>> <</if>> <<if $regen && $health lt $MaxHealth>> <p> You regenerate <b class='hp'><<=Math.round($regen)>></b> health. </p> <<health `Math.round($regen)`>> <</if>> <</append>> <<trigger 'UIupdate'>> <<run $('#fight').stop().animate({ scrollTop: $('#fight')[0].scrollHeight}, 800);>> <<stop>> <</if>> <</repeat>> <</if>> <</widget>>
<<if !tags().includes('combat')>> <h2>Blast arm</h2> <div class='EvenSpace'> <img @src="setup.BlastArm.texture"> <img @src="setup.BlastArm.icon"> </div> <h3>Damage</h3> Close quarters: 20 <br> Short range: 10 <h3>Modifiers</h3> Ranged, ammo type <h3>Effect</h3> <p>Close range attacks knock opponents back</p> <<else>> <<skill setup.BlastArm 'Fire blast arm'>> <<AP 1>> <<if _range is 1>> <<range +1>> <<append "#fight">> <p> The point-blank blast <<EnDMG 1 20>> and pushes your opponent back <<ammo>> </p> <</append>> <<else>> <<append "#fight">> <p> The ranged blast <<EnDMG 1 10 _rangemodifier>> <<ammo>> </p> <</append>> <</if>> <</skill>> <</if>>
<<if $enhealth lt (100*$difficulty) and $enemyAP is 4>> <<divider 'buff'>><br> The robot emits a ramping whir and attacks with renewed vigor. <<set $enemyAP ++>> <<elseif _range is 1>> <<divider 'moveback'>><br> The enemy hits you, dealing <<DMG 1 6>> and pushing you back. <<range 1>> <<elseif _range == 2 && _action == 1>> <<divider 'enemy'>><br> In a swift motion, the robot draws its pistol and shoots you for <<DMG 1 10>>. <<elseif _range == 2 && _action == 3>> <<divider 'enemy'>><br> The robot fires a wrist-mounted rocket at you, dealing <<DMG 1 20>>. <<elseif _range is 2>> <<divider 'enemy'>><br> In a swift motion, the robot fires two quick shots which deal <<DMG 2 6>>. <<elseif _range gt 2>> <<divider 'movefor'>><br> The robot advances menacingly toward you. <<range -1>> <</if>>
<<if $enhealth gt (200*$difficulty)>> <<if _range gt 1>> The living wave rushes toward you <<set _range -=1>> <<if _range is 1>> and hits you head on, dealing <<DMG 1 20>> and knocking you down. <<set _ground to true>> <<else>>.<</if>> <<else>> The swarm lashes out, dealing <<DMG 3 10>>. <</if>> <<elseif $enhealth gt (150*$difficulty)>> <<if $enemy.AP gt 5>><<set $enemy.AP = 5>><</if>> <<if _range gt 1>> The living wave rushes toward you. <<set _range -=1>> <<else>> The swarm lashes out, dealing <<DMG 4 5>>. <</if>> <<elseif $enhealth gt (100*$difficulty)>> <<if $enemy.AP gt 4>><<set $enemy.AP = 4>><</if>> <<if _range gt 1>> The scarabs advance toward you. <<set _range -=1>> <<else>> The scarabs attack, dealing <<DMG 3 5>>. <</if>> <<elseif $enhealth gt (50*$difficulty)>> <<if $enemy.AP gt 3>><<set $enemy.AP = 3>><</if>> <<if _range gt 1>> The remaining scarabs advance toward you. <<set _range -=1>> <<else>> The remaining scarabs attack, dealing <<DMG 2 5>>. <</if>> <<elseif $enhealth lte (50*$difficulty)>> <<include "CBbehav">> <</if>>
<<widget "stun">> <<set _stunchance = (1-($enhealth/$MaxEnhealth))*100+$stunmodifier-_enstun*20, _n = _args[0] ?? 1, _st = 0>> <<for _i = 0; _i lt _n; _i++>> <<if _stunchance gt random(0,100)>> <<set _enstun ++, _st ++>> <</if>> <</for>> <p class='small'> <<if _st>> The enemy is stunned for <b class=red>_st</b> action<<= _st gt 1? 's':''>>. <<else>> Stun failed. <</if>> </p> <</widget>>
<<widget "CombatUI">> <div id="CombatUI"> /* AP counter */ <<on 'statusUpdate' 'div' id 'APcounter'>> <<for _i=0;_i lt $AP;_i++>> <<if _i lt _AP>> <div class='AP'></div> <<else>> <div class='APspent'></div> <</if>> <</for>> <<if _AP gt $AP>> + <<for _i=0;_i lt (_AP-$AP);_i++>> <div class='AP'></div> <</for>> <</if>> <</on>> /* Back - forth */ <<include "moveback">> <<include "movefor">> /* Skill box */ <<on 'skillboxRefresh' 'div' id 'skillbox'>> <<if _playerStun>> <<but 'Unstun yourself (_playerStun AP)' class 'skill' id 1 style `'width:'+_totskills.length*10.2+'em'` data-key 1>> <<set _AP -= _playerStun gt _AP ? _AP : _playerStun, _playerStun = 0>> <<trigger 'skillboxRefresh, statusUpdate'>> <</but>> <<else>> /* Skills */ <<include "skill printer">> <</if>> <</on>> /* Wait, flee */ <<include "wait">> <<include "flee">> </div> <<done>> <<run setup.skillShrink(10)>> <</done>> <</widget>>
<<if _fortified is true>> <<set _fortified to false>> The mechanical mass unfolds like the sentry would and lunges at you, dealing <<DMG 1 30>>. <<set _range to 1>> <<else>> <<include setup.randomBehav.random()>> <</if>>
<<widget "itemequip">> <<hex _args[0] `'Equip '+_args[0].name`>> <<if _args[0].type?.includes('weapon')>> <<if $weapons.length+(_args[0].size? _args[0].size : 1) gt $weaponcapacity>> <<run Dialog.setup(), Dialog.wiki("You can only carry $weaponcapacity weapons."), Dialog.open()>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$weapons['+$weapons.length+']'>> <<set $weapons.push($storage.delete(_args[0])[0])>> <<trigger "statChange">> <</if>> <<elseif _args[0]?.type === 'drone'>> <<if $drones.length+(_args[0].size? _args[0].size : 1) gt $dronecapacity>> <<run Dialog.setup(), Dialog.wiki("You can only carry $dronecapacity drones."), Dialog.open()>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$drones['+$drones.length+']'>> <<set $drones.push($storage.delete(_args[0])[0])>> <<trigger "statChange">> <</if>> <<elseif $equip.length gte $capacity>> <<run Dialog.setup(), Dialog.wiki("Your current frame does not support more than $capacity upgrades. You need to make a choice."), Dialog.open()>> <<elseif _args[0].type === "ammo" and $ammotype !== "None">> <<run Dialog.setup(), Dialog.wiki("You already have a type of ammunition equipped."), Dialog.open()>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$equip['+$equip.length+']'>> <<set $equip.push($storage.delete(_args[0])[0])>> <<trigger "statChange">> <</if>> <</hex>> <</widget>>
<<widget "itemstore">> <<hex _args[0] `'Store '+_args[0].name`>> <<set _args[0].dir = '$storage['+$storage.length+']'>> <<if _args[0].type?.includes('weapon')>> <<unequip _args[0]>> <<set $storage.push($weapons.delete(_args[0])[0])>> <<elseif _args[0]?.type === 'drone'>> <<unequip _args[0]>> <<set $storage.push($drones.delete(_args[0])[0])>> <<else>> <<unequip _args[0]>> <<set $storage.push($equip.delete(_args[0])[0])>> <</if>> <<trigger "statChange">> <</hex>> <</widget>>
<<if $health lt 5 and _range gt 1>> Your opponent lunges forward! <<set _range -->> <<elseif _range is 1 and _fortified is false and $enhealth lt 50>> The robot protects itself behind its heavy shield. <<set _fortified to true>> <<elseif _range is 1 and _fortified is true>> The robot lunges from behind its shield to hit you, dealing <<DMG 1 15>>. <br> It is now vulnerable. <<set _fortified to false>> <<elseif _range is 1>> The robot hits you with its baton, dealing <<DMG 1 15>>. <<set _fortified to false>> <<elseif _range is 2 and _fortified is true>> The robot hides behind its shield, waiting for you to make the next move. <<elseif _range is 2 and _action is 2>> The robot pulls out a gun and shots you from behind its shield, dealing <<DMG 1 10>>. <<elseif _range gt 1>> The robot advances in your direction. <<set _fortified to false>> <<set _range -->> <</if>>
The sun rises on the horizon. It casts a crimson light on the underbelly of the low hanging clouds. Who in the busy Ibadan below witnesses these morning hews? Millions? Hundreds? Only you? Faded shades of purple reflect on the uneven roofs, on the smooth domes and the covered streets that stretch like veins throughout the city. To the right, a sustended bridge carries the Liebu overpass over the low dark sea of the slums. In a few hours, the heat above ground will be unbearable. It is time to take the first, and last, breath of fresh air of the day. Behind you, the elevator emits a light whirr, it feels like an impedus to [[get going.|Intro2]]
<<widget "itembuy">> <<if _args[0].price>> <<set _price = _args[0].price>> /* Redo fancy math...*/ /* Hex captures the price */ <<hex _args[0] `_price gt $money ? 'Cannot buy' : 'Buy '+_args[0].name`>> <<if $money lt _price>> <<run Dialog.setup(), Dialog.wiki("You can't afford the item."), Dialog.open()>> <<else>> <<set $money -= _price>> <<run State.variables[_ref].delete(_args[0])>> <<itemget _args[0]>> <<trigger 'UIupdate'>> <<run $('#'+_id).replaceWith($(`<div class="hex shadowhex">${_args[0].name} bought.</div>`))>> <</if>> <</hex>> <</if>> <</widget>>
<p>Find Efi as a corpse instead of meeting her, chance-based.</p> <p>Loot the bespoke grapple arm, a tonic and an ID...</p> <div class='center'> <<itemloot setup.EfisArm>> <<itemloot setup.Tonic>> </div>
<<set setup.Upgrades = { common : [ setup.AimingMod, setup.BlastArm, setup.ExtraStorage, setup.CombatCapacitor, setup.ConBlast, setup.CQCMod, setup.DisCore, setup.EscalationMod, setup.GrappleArm, setup.HiExplosives, setup.KinCharger, setup.Missiles, setup.OverdriveCore, setup.Plating, setup.ReconSwarm, setup.StackOverflow, setup.ThunderKick, setup.WepInterface, setup.DroneInterface, setup.AmmoSynt, setup.CritScanner, setup.AdaptAim, setup.ShockSling ], advanced : [ setup.AdvAimingMod, setup.AdvBlastArm, setup.AdvExtraStorage, setup.AdvCombatCapacitor, setup.AdvConBlast, setup.AdvCQCMod, setup.AdvDisCore, setup.AdvEscalationMod, setup.AdvGrappleArm, setup.AdvHiExplosives, setup.AdvKinCharger, setup.AdvMissiles, setup.AdvOverdriveCore, setup.AdvPlating, setup.AdvReconSwarm, setup.AdvStackOverflow, setup.AdvThunderKick, setup.AdvWepInterface, setup.AdvDroneInterface, setup.AdvAmmoSynt, setup.AdvCritScanner, setup.WristMissile, setup.AcidRounds, setup.ExplosiveRounds, setup.ShockRounds, setup.KinStrike, setup.AdvShockSling ], rare : [ setup.RareAimingMod, setup.RareBlastArm, setup.RareCombatCapacitor, setup.RareConBlast, setup.RareCQCMod, setup.RareDisCore, setup.RareEscalationMod, setup.RareGrappleArm, setup.RareHiExplosives, setup.RareKinCharger, setup.RareOverdriveCore, setup.RarePlating, setup.RareReconSwarm, setup.RareStackOverflow, setup.RareThunderKick, setup.RareWepInterface, setup.RareDroneInterface, setup.RareAmmoSynt, setup.RareCritScanner, setup.WeaponsSpecialist, setup.DodgeModule ], spec : [setup.AeonHand, setup.BasicStrike] }>> <<run for (const key in setup.Upgrades){ setup.Upgrades[key].forEach((item, i) => { item.dir = `setup.Upgrades.${key}[${i}]` ; }); }>> <<set setup.Weapons = [ setup.RotaryCannon , setup.Pistol , setup.Darts , setup.Bullpup , setup.SMG , setup.Sword , setup.PipePistol , setup.HEGrenade, setup.StunGrenade, setup.Revolver, setup.CombatDrone , setup.MissileDrone , setup.HealerDrone]>> <<for _i, _item range setup.Weapons>> <<set _item.dir = 'setup.Weapons['+_i+']'>> <</for>> /* Full weapon list !*/ /*<<set setup.Weapons = [ setup.RotaryCannon , setup.Pistol , setup.Rifle , setup.Darts , setup.Shield , setup.Bullpup , setup.CombatDrone , setup.MissileDrone , setup.HealerDrone, setup.SMG , setup.Sword , setup.PipePistol , setup.ScrapRifle, setup.HEGrenade, setup.StunGrenade, setup.AcidGrenade, setup.Revolver, setup.autopistol]>>*/ <<set setup.SpecWeapons = [setup.Gunblade, setup.Katana]>> <<for _i, _item range setup.SpecWeapons>> <<set _item.dir = 'setup.SpecWeapons['+_i+']'>> <</for>> <<set setup.Frame = { common : [ setup.HPup, setup.IntegratedShield, setup.NanoNest ], advanced : [ setup.AdvHPup, setup.AdvIntegratedShield, setup.ArmoredCore, setup.AdvNanoNest ], rare : [ setup.RareHPup, setup.RareIntegratedShield, setup.ExtraCapacity, setup.WeaponCapacity, setup.OverchargeCore ] }>> <<run for (const key in setup.Frame){ setup.Frame[key].forEach((item, i) => { item.dir = `setup.Frame.${key}[${i}]` ; }); }>> <<set setup.Consumables = [ setup.Scarab, setup.Medkit, setup.InfectedMedkit, setup.AdvMedkit, setup.Tonic, setup.AdvTonic, setup.ShieldBooster, setup.InnerNetworkKey, setup.TransferKey, setup.RandTransferKey, setup.AdvTransferKey, setup.RareTransferKey, setup.DemoCharge]>> <<for _i, _item range setup.Consumables>> <<set _item.dir = 'setup.Consumables['+_i+']'>> <</for>> /* Shops */ <<set $MekaPool = [...setup.Upgrades.common.randomMany(2), ...setup.Upgrades.advanced.randomMany(2), setup.Weapons.random(), setup.Frame.common.random(), setup.Frame.advanced.random() ]>> <<run $MekaPool.shuffle()>>
<<silently>> /* Creates temp clones of story vars*/ <<for _i range setup.stats>> <<= "<<set _"+_i+" = $"+_i+">>" >> <</for>> <</silently>> <<on 'statChange' 'div' id 'statScreen'>> <h3>STATS</h3> <<statchange 'AP' 'Action points'>> <br> <<statchange 'regen' 'Regen'>> <<statchange 'healmodifier' 'Healing modifier'>> <<statchange 'DMGresist' 'Damage reduction'>> <br> <<statchange 'stunmodifier' 'Odds to stun'>> <br> <<statchange 'weaponsmodifier' 'Weapons affinity'>> <br> <<statchange 'cqcmodifier' 'CQC damage'>> <<statchange 'rangemodifier' 'Ranged damage'>> <<statchange 'blastmodifier' 'Explosive damage'>> <<statchange 'elecmodifier' 'Electric damage'>> <br> <<statchange 'droneDMG' 'Drone damage'>> <<statchange 'droneaffinity' 'Drone affinity'>> <br> <<statchange 'ammotype' 'Ammunition type'>> <br> <<statchange 'extrause' 'Extra uses'>> <<statchange 'allin' 'Extra attack odds'>> <br> <<if $kincharge>> <<statchange 'kincharge' 'Kinetic recharge'>> <</if>> <<if $freemove>> <b>Free move</b> <</if>> <<if $freeshot>> <b>Free pistol shot</b> <</if>> <</on>>
<p> The slender silhouette of a war dog lunges out of the darkness. </p> <<a "Fight back." id 2 goto 'Combat'>> <<fight setup.RabidDog 'rand'>> <</a>>
[[Leave.|Consumable items]] William Shopmann is sitting behind the counter, <<= either("wearing his usual tophat.","reading a book which looks miniscule in his long hands.","polishing some baroque trinket with a cloth.","he grins in your direction as you enter the shop.")>> <center><img src="https://cdn.discordapp.com/attachments/949715863479672913/962393804369973278/shopmanndivid.png"/></center> <span class="shm">"Are you here to [[buy|ShopBuy]] or to <<link 'sell'>> <<if $storage.length is 0>> <<replace '#s'>> You have nothing to sell. <</replace>> <<else>> <<goto 'ShopSell'>> <</if>> <</link>> ?"</span> <span id="s"></span> <<include "bounty1">>
- Sell stuff (needs to be in the storage part of your inventory for that!)- <<if $storage.length gt 6>> <div class="grid"> <<for _i to 0; _i < $storage.length; _i++>> <<itemsell $storage[_i]>><br> <</for>> </div> <<else>> <div class="center"> <<for _i to 0; _i < $storage.length; _i++>> <<itemsell $storage[_i]>><br> <</for>> </div> <</if>> [[Leave.|ShopMain]]
<<widget "itemsell">> <<if _args[0].price>> /* Makes sure player cannot sell their hand...*/ <<set _price = Math.round(_args[0].price/2)>> <<capture _price>> <<hex _args[0] `'Sell '+_args[0].name`>> <<set $money += _price>> <<if $equip.includes(_args[0])>> <<set $equip.delete(_args[0])>> <<unequip _args[0]>> <<elseif $weapons.includes(_args[0])>> <<set $weapons.delete(_args[0])>> <<unequip _args[0]>> <<else>> <<set $storage.delete(_args[0])>> <</if>> <<trigger 'UIupdate'>> <<run $('#'+_id).replaceWith($(`<div class="hex shadowhex">${_args[0].name} sold.</div>`))>> <</hex>> <</capture>> <</if>> <</widget>>
The shopkeeper leads you to an adjoining room, shelves and crates clutter the small space. In the half-light cast by the ceiling fixture, you recognize a multitude of mechanical limbs and other implants. <<shm "I am afraid you will have to do some digging.">> Shopmann mutters, still standing at the door. It is evident that his hat would not clear the top. <div class="grid"> <<for _item range $ShopmannPool>> <<itembuy _item>><br> <</for>> </div> <<shm "This one is a gem.">>, the shopkeeper comments as you brush past one of the shelves. <<shm "An implant capacity upgrade. Of course it will only go at a fair price...">> <div class="center"> <<itembuy setup.ExtraCapacity>> </div> <<shm "If you ever find yourself in possession of undesired merchandise, I will gladly take it off your hands. At a reasonable price at that.">> [[Go back to the main room.|ShopMain]]
You step inside the bare cabin, the doors close shut. Through the elongated hexagonal window, you behold the metropolis below. Jagged roofs rush toward you at high speed, then engulf the cabin. It takes some time for your eyes to adapt to the oily darkness. The cabin shakes and rumbles, then slows down. Through the window, you behold a vast domed expanse, bustling with life. It is the Old Gra surface hub. Covered streets stretch in every direction, crowded with people, shops and animals. Officially, the Old Gra disctrict houses half a million over three depth levels. The elevator comes to a stop and the door hisses open.
<<if !tags().includes('combat')>> <h2>Advanced blast arm</h2> <div class='EvenSpace'> <img @src="setup.BlastArm.texture"> <img @src="setup.BlastArm.icon"> </div> <h3>Damage</h3> <p> Close quarters: 30 <br> Short range: 15 </p> <h3>Modifiers</h3> Ranged, ammo type <h3>Effect</h3> <p>Close range attacks knock opponents back</p> <<else>> <<skill setup.BlastArm 'Fire advanced blast arm'>> <<AP 1>> <<if _range === 1>> <<range +1>> <<append "#fight">> <p> The point-blank blast <<EnDMG 1 30>> and pushes your opponent back <<ammo>> </p> <</append>> <<else>> <<append "#fight">> <p> The pellets hit your opponent at medium range, <<EnDMG 1 15 _rangemodifier>> <<ammo>> </p> <</append>> <</if>> <</skill>> <</if>>
<<a " <img src ='https://cdn.discordapp.com/attachments/949715863479672913/1014617443131478078/fleewip.png'> <div class='skillinfo'>Try to flee</div>" key settings.keys.flee data-key settings.keys.flee class 'skillShort'>> <<if _AP && $health gt 0>> <<if _range + _AP gt random(0, 10)>> <<AP 0 'moveback'>>/* Just triggers the scroll effect */ <<run $('#CombatUI a').ariaDisabled(true); $('#fight').wiki(" <p>You manage to flee! <<a 'Escape' goto 'Game'>><</a>> </p> "); $pos = $rooms[$pos].possible.random()>> <<else>> <<AP 1 'moveback'>> <<run $('#fight').wiki(" <p>You don't manage to flee!</p> ")>> <</if>> <</if>> <</a>>
"I have a vested interest in others believing that my only loyalty lies in money. If only..." "Sadly business down here means getting involved body and soul, relatives too." "It a young man's gample to think one can meddle yet not be swallowed." "And what if you prick me, do I not bleed? If you poison me, do I not die? And if you wrong me, shall I not revenge?" "The villainy you teach me I will execute, and it shall go hard but I will better the instruction." William Shopmann, 68, former envoy of a big armament firm in the third civil war. Sided with the Hausa rebellion because he was approached by a seductive Hausa spy, was fired by the firm, when the spy learned it, left him. Spent years in small trades, slept in the streets. Now, he's an established and ruthless business man. At some point, you meet Shopmann's former love as a head-hunter, going for you. Option to bring her dogtag back to William. Of course, as a highly observant man, he knows the number. Thanks you for bringing closure to the matter, that the ambivalent lesson of growing old is learning to let go of the past.
<<widget "scrap">> <<set _gain = Math.round(( _args[0] ? _args[0] : $enemy.health/10 ) * randomFloat(0.9,1.1) * $difficulty), $scraps += _gain>> <<if _args[0]>> <p> You find <b class='scp'>_gain</b> scraps. </p> <<else>> <p> You salvage <b class='scp'>_gain</b> scraps from your destroyed opponent. </p> <</if>> <<trigger 'UIupdate'>> <</widget>>
<<if _range === 4>> <<set _randA = random(1)>> <<divider `_randA ? 'doubleback' : 'moveback'`>> <p> The assasin <<= _randA ? 'lounges' : 'advances'>> toward you. <<range `_randA ? -2 : -1`>> </p> <<elseif _range === 3>> <<if _enemyuse>> <<divider 'enemy'>> <p> Your opponent throws an explosive dart which releases in a blinding flash, <<DMG 1 15>>. </p> <p class='small'>You are stunned.</p> <<set _playerStun++, _enemyuse-->> <<elseif _action === 4>> <<divider 'enemy'>> <p> The woman throws a knife, <<DMG 1 5>>. </p> <<else>> <<divider 'doubleback'>> <p> Your opponent lounges forward. <<range -2>> </p> <</if>> <<elseif _range === 2>> <<if _enemyuse>> <<divider 'moveback'>> <p> The assassin unsheathes and dashes, the powerful slash deals <<DMG 1 20 '' 'noverb'>>. </p> <<set _enemyuse-->> <<range -1>> <<elseif _action === 4>> <<divider 'movefor'>> <p> You opponent takes a step back, winding up for another attack. </p> <<range 1>> <<elseif random(1)>> <<divider 'enemy'>> <p> The assassin throws a knife, <<DMG 1 7>>. </p> <<else>> <<divider 'moveback'>> <p> The assassin dashes to close the distance. </p> <<range -1>> <</if>> <<else>> <<if _enemyuse || !random(2)>>/* Set up the super slash */ <<divider 'movefor'>> <p> The woman kicks you backward, <<DMG 1 5>>. </p> <<range 1>> <<elseif !_ground && random(4) === 4>> <<divider 'enemy'>> <p> The assassin manages to throw you to the ground, <<DMG 1 6>>. <<set _ground = true>> </p> <<else>> <<divider 'enemy'>> <p> <<= either(" A lightning-fast slash deals <<DMG 1 15 '' 'noverb'>>. ",' She assassin slashes at you, <<DMG 2 8>>. ')>> </p> <</if>> <</if>>
<<widget 'lights'>> <<run $('#lightgrid').css('grid-template-columns', 'repeat('+_args[0]+', 1fr)')>> <<set $spotmax = _args[0]*5>> <<trigger 'spotChange'>> <</widget>>
<<widget "attack" container>> <<if _AP is 0>> <<elseif $enhealth lte 0>> <<elseif _blinded is true and _range gt 1>> <<replace "#next">> <div class="warning"> You are blinded. You cannot use ranged skills. </div> <</replace>> <<elseif _range lt _args[0].rmin>> <<replace "#next">> <div class='warning'> The enemy is too close to use this skill. </div> <</replace>> <<elseif _range gt _args[0].rmax>> <<replace "#next">> <div class='warning'> The enemy is too far for the attack to reach. </div> <</replace>> <<else>> <<set _last to "attack">> _contents <</if>> <</widget>>
function lookAhead(offset){ room return new $pos } <<if $rooms[$pos-$MaxX].type === 'corridor'>> <<set $pos -= $MaxX*2>> <<else>> <<set $pos -= $MaxX>> <</if>> <<trigger 'mapRefresh'>>
<<widget "DMG">> /* ---------- Styling --------------*/ <<set _style = _args[2] || 'orange'>> <<set _noverb = _args.includes('noverb') ? true : false>> /* ------------------------ Damage basis --------------------------- */ /* $enGlobal => 100 by default, _DMGresist => 0 by default */ <<set _damage = _args[1]*(((_enGlobal ?? 0)-_DMGresist)/100)>> <<run $('#fight').wiki($player.ondamage)>> /* ---------------------- Single attack ---------------------------- */ <<if _args[0] === 1>> <<if _block>> <<= _noverb? '' : 'removing'>> <div class='block'>1</div> block <<set _totDMG = 0, _block -->> <<else>> <<set _totDMG = Math.round(_damage*randomFloat(0.8,1.2))>> <<= _noverb? '' : 'dealing'>> <b @class=_style>_totDMG</b> damage <</if>> <<else>> /* ---------------------- Multiple attacks ------------------------ */ <<set _totDMG = _blocked = 0, _damageArray = []>> /* Set damage numbers */ <<for _i to 0; _i lt _args[0];_i++>> <<if _block>> <<set _blocked ++, _block -->> <<else>> <<set _damageArray.push(Math.round(_damage*randomFloat(0.8,1.2)))>> <</if>> <</for>> <<set _totDMG = _damageArray.reduce((a, b) => a + b, 0)>> /* ----------------------- Display damage -------------------------- */ <<if _blocked>> <<= _noverb? '' : 'removing'>> <div class='block'>_blocked</div> <<= _blocked gt 1? 'blocks' : 'block'>> <<= _damageArray.length? 'and' : ''>> <</if>> <<hover '' capture true>> <<for _i=0; _i lt _damageArray.length; _i++>> <<switch _i>> <<case 0>> <<= _noverb? '' : 'dealing'>> <b @class=_style>_damageArray[_i]</b> <<case _damageArray.length-1>> and <b @class=_style>_damageArray[_i]</b> <<default>> , <b @class=_style>_damageArray[_i]</b> <</switch>> <</for>> <<swap>> dealing <b @class='_style'>_totDMG</b> total <</hover>> <<if _damageArray.length>> damage<</if>> <<timed 0.01s>><<trigger 'action'>><</timed>> <</if>> /* health removal */ <<if _shield>> <<set _shield -= _totDMG >> <<if _shield lt 0>> <<health _shield>> <<set _shield = 0>> <</if>> <<trigger 'UIupdate'>> <<run $('.shield').addClass('flicker1') .on('animationend', function() { $(this).removeClass('flicker1').off(); });>> <<else>> <<health `-_totDMG` >> <</if>> <</widget>>
/* Active items */ /* Pattern! charge: ['variable', 'extracharge(boolean)', 'No charges message'], skillname: 'custom name for the skill container hover', skillextra: 'extra display in the skill container', ap: 'ap cost(number)', prompt: 'display sentence', num: 'number of attack instances', damage: 'damage value', crit: 'multiplier', modifiers: 'variable or array of variables as strings', effect: 'extra effects (stun, loss of charges...)', preAttack: 'happens before attack' cond: '$var gt _var... a condition to avaluate' noMessage : 'item condition is not fulfilled' */ /* Default strike as an item */ <<set setup.BasicStrike = { name: "Standard arm" , skillname: 'Strike', damage: 8, modifiers: '$cqcmodifier', desc : {flavor : "<p>A basic mechanical arm, enables fine motor control... and punching.</p>", Range : "Close quarters", Damage : 8, Modifiers : "CQC" }, texture: setup.locLoad('hand'), icon: setup.locLoad('punch'), qual: 'common', rmax: 1 }>> /* Overdrive core ---------------------------------------------------*/ <<set setup.OverdriveCore = { name: "Overdrive core", ap : -1, charge: ['over', true, 1], prompt : "Power surges in your body.<br> + <div class='AP'/>", desc : {Effect : "<span>Grants <div class='AP'/> on use.</span>"}, icon: setup.locLoad('overdriveicon'), texture: setup.locLoad('OD'), price: 100, qual: 'common', modif: {over : 1}}>> <<ni 'setup.AdvOverdriveCore' setup.OverdriveCore `{ name: "Advanced overdrive core", ap : -2 , charge : ['advover', true, 1], prompt : "Power surges in your body.<br>+ <div class='AP'/><div class='AP'/>", desc : {Effect : "<span>Grants <div class='AP'/><div class='AP'/> on use.</span>"}, price: 150, qual: 'adv', modif: {advover : 1}}`>> <<set setup.RareOverdriveCore = { name: "Rare overdrive core", desc: {Passive_effect : "<span>Grants <div class='AP'/> each turn.</span>"}, texture: setup.locLoad('OD'), type: "passive", price: 250 , qual: 'rare', modif: {AP : 1}}>> /* Stack overflow ---------------------------------------------------*/ <<ni 'setup.StackOverflow' `{ name: "Drug injector", charge: ['stackover', 'true', 2], prompt: "Power surges in your body.<br>+ 10% damage resistance<br>+ 10% damage dealt", ap : 0, effect : '<<set _heat += 10, _DMGresist += 10>>', desc : { flavor: 'Not all strength stems from mechanical improvement...', Effect : "<p>Increases damage resistance by 10% for a turn.<br>Increases all damage dealt by 10% for a turn.</p>"}, texture: setup.locLoad('injector'), icon: setup.locLoad('injectoricon'), price: 100, qual: 'common', modif: {stackover : 2}}`>> <<ni 'setup.AdvStackOverflow' setup.StackOverflow `{ name: "Advanced drug injector", charge : ['advstackover', true, 2], prompt: 'Power surges in your body.<br>+ 20% damage resistance<br>+ 20% damage dealt', effect : '<<set _heat += 20, _DMGresist += 20>>', desc : { flavor: 'Not all strength stems from mechanical improvement...', Effect : "<p>Increases damage resistance by 20% for a turn.<br>Increases all damage dealt by 20% for a turn.</p>"}, price: 150, qual: 'adv', modif: {advstackover : 2}}`>> <<ni 'setup.RareStackOverflow' setup.StackOverflow `{ name: "Rare drug injector", ap: -1, charge: ['rstackover',true, 2], prompt: 'Immense power surges in your body.<br>+1 AP<br>+ 25% damage resistance<br>+ 25% damage', effect : '<<set _heat += 25, _DMGresist += 25>>', desc : { flavor: 'Not all strength stems from mechanical improvement...', Effect : "<p>Increases damage resistance by 25% for a turn.<br>Increases all damage dealt by 25% for a turn.<br>Grants <div class='AP'/> on turn.</p>"}, price: 250, qual: 'rare', modif: {rstackover : 2}}`>> /* Combat capacitor--------------------------------------------------*/ <<set setup.CombatCapacitor = { name: "Combat capacitor", prompt: "The discharge ", damage : 5, modifiers : ['$elecmodifier', '_rangemodifier'], effect : '<<stun>>', texture: setup.locLoad('combatcapacitor'), icon: setup.locLoad('combatcapacitoricon'), desc: {Range : "Close quarters, short range.", Modifiers : "Electricity, ranged.", Effect : 'Stun: 1', Passive_effect : 'Increases odds to stun' }, price: 80 , qual: 'common', modif: {stunmodifier : 5 }, rmax: 2 }>> <<ni 'setup.AdvCombatCapacitor' setup.CombatCapacitor `{ name: "Advanced combat capacitor", damage : 7, effect : '<<stun 2>>', desc: {Range : "Close quarters, short range.", Modifiers : "Electricity, ranged.", Effect : 'Stuns: 2', Passive_effect : 'Increases odds to stun' }, price: 120 , qual: 'adv', modif: {stunmodifier : 10 }}`>> <<ni 'setup.RareCombatCapacitor' setup.CombatCapacitor `{ name: "Rare combat capacitor", num: 2, damage : 6, price: 210 , qual: 'rare', modif: {stunmodifier : 15 }}`>> /*-------------------------------Missiles----------------------------*/ <<ni 'setup.Missiles' `{ name: "Integrated missiles", charge : ['missiles','true', 2], noMessage : 'No missiles left', prompt: "The explosive salvo ", num: 3, damage : 8, modifiers : ['$blastmodifier', '_rangemodifier'], desc : { flavor : 'Unleash a barrage of guided explosive projectiles upon your foes.', Modifiers : 'Blast and range damage.', Uses : "<<= Math.round(2*$extrause)>>"}, texture: setup.locLoad('intmis'), icon: setup.locLoad('intmisicon'), price: 80 , qual: 'common', modif : {missiles : 2}, rmin: 3 }`>> <<ni 'setup.AdvMissiles' setup.Missiles `{ name: "Advanced integrated missiles", charge : ['advmissiles','true', 2], prompt: "Fires rains down on your opponent and", num: 5, effect: "<<set _advmissiles -->><<trigger 'skillboxRefresh'>>", desc : { flavor : 'Unleash a barrage of guided explosive projectiles upon your foes.', Modifiers : 'Blast and range damage.'}, texture: setup.locLoad('advintmis'), icon: setup.locLoad('advintmisicon'), price: 120 , qual: 'adv', modif : {advmissiles : 2},}`>> <<set setup.WristMissile = { name: "Wrist-mounted missile", charge : ['wristmissiles','true', 1], prompt: 'The missile', damage : 18, ap: 0, skillextra: '<div class="freeaction"/>', desc : {flavor : 'The arm-mounted missile launches in a second.', Modifiers : 'Blast and range damage.'}, texture: setup.locLoad('wristmissile'), icon: setup.locLoad('wristmisicon'), price: 120 , qual: 'adv', modif : {wristmissiles : 1}, rmin: 3 }>> /* Blast arm---------------------------------------------------------*/ <<ni 'setup.BlastArm' `{ name: "Blast arm", skillname: 'Fire blast arm', damage : '30-_range*10', prompt : '<<if _range === 1>>The point-blank blast<<else>>The shot<</if>>', effect : '<<if _range === 1>> and pushes your opponent back.<<range 1>><</if>><<ammo>>', texture: setup.locLoad('blastarm'), icon: setup.locLoad('BAicon'), desc : { flavor : 'The built-in mechanism fires shotgun shells.<br>What the contraption lacks in accuracy it makes up for in stopping power.', Damage : '<b>Close quarters</b> : 20 <br> <b> Short range</b> : 10', Modifiers : 'Ranged, ammo type', Effect : 'Close quarters attacks push opponents back.' }, price: 80 , qual: 'common', rmax: 2}`>> <<ni 'setup.AdvBlastArm' setup.BlastArm `{ name: "Advanced blast arm", damage : '45-_range*15', desc : { flavor : 'The built-in mechanism fires shotgun shells.<br>What the contraption lacks in accuracy it makes up for in stopping power.', Damage : '<b>Close quarters</b> : 30 <br> <b> Short range</b> : 15', Modifiers : 'Ranged, ammo type', Effect : 'Close quarters attacks push opponents back.' }, price: 120 , qual: 'adv'}`>> <<ni 'setup.RareBlastArm' setup.AdvBlastArm `{ name: "Rare blast arm", damage : '55-_range*20', effect : '<<if _range === 1>> and pushes your opponent back.<<range 1>><</if>><<ammo>><<stun>>', desc : { flavor : 'The built-in mechanism fires shotgun shells.<br>What the contraption lacks in accuracy it makes up for in stopping power.', Damage : '<b>Close quarters</b> : 35 <br> <b> Short range</b> : 15', Modifiers : 'Ranged, ammo type', Effect : 'Close quarters attacks push opponents back and have a chance to stun.' }, price: 200 , qual: 'rare'}`>> /*-------------------------- Grapple arms ---------------------------*/ <<set setup.GrappleArm = { name: "Grapple arm", skillname : 'Throw grapple', prompt : 'The grapple pulls you to your opponent and', num : 1 , damage : 3 , effect : '<<range -2>>', divider : 'grapple', desc : {Effect : 'Pulls you toward the opponent.'}, texture: setup.locLoad('grapplearm'), icon: setup.locLoad('grapplearmicon'), price: 80 , qual: 'common', rmin : 2, modif : {grapple : 1}}>> <<ni 'setup.EfisArm' setup.GrappleArm `{ name: "3F1 grapple arm", qual: 'spec', modif : {grapple : 1, efisArm : 1}}`>> <<ni 'setup.AdvGrappleArm' setup.GrappleArm `{ name: "Advanced grapple arm", effect : '<<range -2>><br><<if _range === 1>>Followed by a quick strike for <<EnDMG 1 10 "$cqcmodifier" "orange" "noverb">><</if>>', desc : {Effect : 'Pulls you toward the opponent.<br>Follow up with a 10 damage strike if you end up at close quarters.'}, price: 120 , qual: 'adv'}`>> <<ni 'setup.RareGrappleArm' setup.GrappleArm `{ name: "Rare grapple arm", ap : 0 , damage : 5, prompt : 'The grapple pulls you to your opponent and', skillextra: '<div class="freeaction"/>', desc : { AP_cost : 0 , Effect : 'Pulls you toward the opponent.'}, price: 160 , qual: 'rare'}`>> /*Thunder kicks -----------------------------------------------------*/ <<set setup.ThunderKick = { name: "Thunder kick", damage : 12, modifiers : ['$cqcmodifier', '$elecmodifier'], effect : '<<stun>>', desc : { Modifiers : 'CQC, electric damage', Effect : 'Stun : 1', Passive_effect : 'Increases odds to stun'}, texture: setup.locLoad('thunderkick'), icon: setup.locLoad('thunderkickicon'), price: 80 , qual: 'common', modif : {stunmodifier : 5}, rmax: 1 }>> <<ni 'setup.AdvThunderKick' setup.ThunderKick `{ name: "Advanced thunder kick", damage : 18, price: 120 , qual: 'adv', modif : {stunmodifier : 10}}`>> <<ni 'setup.RareThunderKick' setup.ThunderKick `{ name: "Rare thunder kick", prompt: "The powerful kick", damage : 22, price: 200 , qual: 'rare', modif : {stunmodifier : 15}}`>> /* Recon swarms------------------------------------------------------*/ <<set setup.ReconSwarm = { name: "Reconstructor swarm", cond : '$health !== $MaxHealth', noMessage : 'Full health', preAttack : '<<set _heal = Math.round(8*$healmodifier*randomFloat(0.8,1.2))>><<if _heal gt $MaxHealth - $health>><<set _heal = $MaxHealth - $health>><</if>><<health _heal>>', prompt : "The buzzing swarm heals you for <b class='hp'>_heal</b> HP.", effect : "<<trigger 'skillboxRefresh'>>", desc: {Effect : "Heals you for <b class='hp'>8</b> HP in combat.", Passive_effect : 'Increases out of combat regeneration.', Modifiers : 'Healing' }, texture: setup.locLoad('recswarm'), icon: setup.locLoad('reconswarm'), price: 80, qual: 'common', modif : {regen : .5}}>> <<ni 'setup.AdvReconSwarm' setup.ReconSwarm `{ name: "Advanced reconstructor swarm", preAttack : '<<set _heal = Math.round(12*$healmodifier*randomFloat(0.8,1.2))>><<if _heal gt $MaxHealth - $health>><<set _heal = $MaxHealth - $health>><</if>><<health _heal>>', desc: {Effect : "Heals you for <b class='hp'>12</b> HP in combat.", Passive_effect : 'Increases out of combat regeneration.', Modifiers : 'Healing' }, texture: setup.locLoad('advswarmtexture'), price: 120, qual: 'adv', modif : {regen : 1, healmodifier : .1}}`>> <<ni 'setup.RareReconSwarm' setup.AdvReconSwarm `{ name: "Rare reconstructor swarm", preAttack : '<<set _heal = Math.round(15*$healmodifier*randomFloat(0.8,1.2))>><<if _heal gt $MaxHealth - $health>><<set _heal = $MaxHealth - $health>><</if>><<health _heal>>', desc: {Effect : "Heals you for <b class='hp'>15</b> HP in combat.", Passive_effect : 'Increases out of combat regeneration.', Modifiers : 'Healing' }, price: 200, qual: 'rare', modif : {regen : 1.5, healmodifier : .2}}`>> /* Concusive blasts--------------------------------------------------*/ <<set setup.ConBlast = { name: "Concusive blast", charge : ['blast','true', 1], damage : '40 - 15*_range', prompt : 'The blast ', modifiers : '$blastmodifier', effect : "<<if _range === 1>>and pushes your opponent back<<range 1>><<stun>><</if>>", desc : {Damage : '<b>Close quarters</b> : 25'+'<br>'+ '<b>Short range</b> : 10', Modifiers : 'Blast damage.', Effect : '<b>Close quarters</b>'+'<br>'+'Stun 1'+'<br>'+ 'Pushes the enemy back.'}, texture: setup.locLoad('concucharge') , icon: setup.locLoad('Cbicon'), price: 80 , qual: 'common', modif : {blast : 1}, rmax: 2 }>> <<ni 'setup.AdvConBlast' setup.ConBlast `{ name: "Advanced concusive blast", charge : ['advblast','true', 1], damage : '45 - 15*_range', prompt : 'The powerful blast ', effect : "<<if _range === 1>>and flings your opponent backward<<range 2>><<stun 2>><<else>>and pushes your opponent back<<range 1>><<stun 1>><</if>>", desc : {Damage : '<b>Close quarters</b> : 30'+'<br>'+ '<b>Short range</b> : 15', Modifiers : 'Blast damage.', Effect : '<b>Close quarters</b> : Stun 2'+'<br>'+ '<b>Short range</b> : Stun 1'+'<br>'+ 'Pushes the enemy back.'}, price: 120 , qual: 'adv', modif : {advblast : 1} }`>> <<ni 'setup.RareConBlast' setup.ConBlast `{ name: "Rare concusive blast", charge : ['rblast', 'true', 1], damage : '60 - 20*_range', desc : {Damage : '<b>Close quarters</b> : 40'+'<br>'+ '<b>Short range</b> : 20', Modifiers : 'Blast damage.', Effect : '<b>Close quarters</b> : Stun 2'+'<br>'+ '<b>Short range</b> : Stun 1'+'<br>'+ 'Pushes the enemy back.'}, price: 200 , qual: 'rare', modif : {rblast : 1} }`>> <<set setup.AdaptAim = { name: "Adaptative aim", prompt : "You take aim, improving ranged damage for you and your drones.", effect : "<<set _rangemodifier += 0.25, _droneDMG += 0.25>>" , desc: {Effect : 'Improves ranged damage for you and your drones by 25% for the coming turn.'}, texture: setup.locLoad('AAtexture') , icon: setup.locLoad('AAicon'), price: 150 , qual: 'common', rmin: 2}>> <<set setup.AeonHand = { name : 'Aeon hand', skillname : 'Claw swipe', damage : 15, modifiers : '$cqcmodifier', crit : 2, critChance : 5, desc : {Range : "Close quarters", Modifiers : "CQC", Critical_modifier : '+ 25% damage, +5% chance', About : "A tribute to the best sci-fi manga you likely haven't read: <br>Hitori Endo's <i>Eden, It's an Endless World</i>."}, texture : setup.locLoad('aeonhand'), icon : setup.locLoad('aeonhandicon'), rmax : 1, qual : 'spec', price : 90 }>> <<set setup.KinStrike = { name : 'Kinetic strikes', skillname : "Strike _turn time<<= _turn ? 's' : ''>>", num : '_turn', damage : 5, modifiers : '$cqcmodifier', desc : {Damage : '5 x combat turns', Range : "Close quarters", Modifiers : "CQC", Effect : 'Deals as many attacks as turns spent in combat.' }, texture : '', icon : setup.locLoad('kinaccu'), rmax : 1, qual : 'adv', price : 150 }>> /*------------------------ Shock sling ------------------------------*/ <<ni 'setup.ShockSling' `setup.CombatCapacitor` `{ name: "Shock sling", prompt: "The cable whips around and", damage : '2 + _range*4', modifiers : '$elecmodifier', texture: setup.locLoad('shocksling'), icon: setup.locLoad('shockslingicon'), desc: {flavor: "A light steel cable with a powerful electrode at its end.<br> A sneaky reference to Samura Hiroaki's <i>Beageruta</i>", Damage : '<b>Close quarters</b> : 6'+'<br>'+ '<b>Short range</b> : 10', Modifiers : "Electricity.", Effect : 'Stun: 1', Passive_effect : 'Increases odds to stun' }, rmax: 2 }`>> <<ni 'setup.AdvShockSling' `setup.ShockSling` `{ name: "Advanced shock sling", damage : '3 + _range*5', desc: {flavor: "A light steel cable with a powerful electrode at its end.<br> A sneaky reference to Samura Hiroaki's <i>Beageruta</i>", Damage : '<b>Close quarters</b> : 8'+'<br>'+ '<b>Short range</b> : 13', Modifiers : "Electricity.", Effect : 'Stun: 1', Passive_effect : 'Increases odds to stun' }, price: 120 , qual: 'adv' }`>>
<<if $money lte 15>> Blurred vision, distant speech. "Doesn't have enough... can't be salvaged..." [[You die.|Death]] <<else>> You've been recovered and reconstructed by the repairshop's automatons. <<set _healable = ($MaxHealth - $health)>> <<set _price = 5+(_healable * (5 - $clinic))>> <<if $money gte _price>> <<set $clinicaffinity += 0.03>> <<set $money -= _price>> <<set $health = $MaxHealth>> <<replace "#hp">>$health / $MaxHealth<</replace>> <<replace "#mon">>$money<</replace>> You've been salvaged and healed to full for the price of N _price . [[OmniClinic]] <<else>> <b class=hp><<= Math.round(_healable*($money/_price))>> HP</b> healed for the price of N _price . <<set $clinicaffinity += 0.01>> <<set $health += Math.round(_healable*($money/_price))>> <<set $money to 0>> <<replace "#hp">>$health / $MaxHealth<</replace>> <<replace "#mon">>$money<</replace>> [[OmniClinic]] <</if>> <</if>>
<<if _range is 3>> <<divider 'movefor'>><br> The machine lunges forward. <<range -1>> <<elseif _range is 2 and _blinded is true>> <<divider 'movefor'>><br> The machines attacks through the smoke, dealing <<DMG 1 10>>. <<range -1>> <<elseif _range is 2>> <<divider 'buff'>><br> An explosion of thick smoke fills the air, <b>blinding you</b>. <<set _blinded to true>> <<elseif _range is 1 and _acid is 0>> <<divider 'enemy'>><br> The machine bites you, dealing <<DMG 1 15 'acid'>>. A corrosive substance drips from its beak. <<set _acid += 5>> <<elseif _range is 1>> <<divider 'enemy'>><br> <<= either("The machine rends you with its mechanical claws, dealing <<DMG 2 8>>.","The machine bites you with its beak, dealing <<DMG 1 15>>.")>> <</if>> <<if _action is $enemy.AP>> <br> <b class=red>It seems to grow increasingly frantic.</b> <<set $enemy.AP ++>> <</if>>
----- Pattern ---- /*<<set setup.Item = { name: "Item name", desc: "- Type -<br>Consumable<br>- Effect -<br>Item effect" , effect: {code : 'Code part', desc : 'Description part'}, texture: "", type: 'consumable', condition: { code : '$y === $x', desc : '$x needs to be $y'}, price: 120 , qual: 'common', stat1: "$variable", modif1: 1 }>>*/ <<set setup.Scarab = { name: "Autonomous scarab", desc: "- Type -<br>Consumable<br>- Effect -<br>Deploys an remote controlled scarab which can scout ahead and defuse traps." , effect: ['','The scarab scouts ahead...'], sit: 'noncombat', texture: "", type: 'consumable', price: 50 , qual: 'common', stat1: "$scarab", modif1: 1 }>> <<set setup.Medkit = { name: "Medkit", desc: "<h2>Medkit</h2><h3>Effect</h3><p>Heals you for <b class=hp>8</b> HP and removes damaging effects</p><h3>Modifiers</h3>Healing" , condition: {code : '$health lt $MaxHealth', desc : 'You are already at maximum health'}, effect: {code : '<<set _heal = Math.round(8*$healmodifier*randomFloat(0.8,1.2))>><<health _heal>>', desc : 'The medkit heals you for <b class=hp>_heal</b> HP.'}, texture: setup.locLoad('medkit'), type: 'consumable', price: 50 , qual: 'common' }>> <<ni 'setup.InfectedMedkit' setup.Medkit `{ effect: {code : '<<set _heal = Math.round(9*$healmodifier*randomFloat(0.8,1.2))>><<health _heal>><<set $infected = true>>', desc: 'The medkit heals you for <b class=hp>_heal</b> HP.<br>A strange tingling spreads in your body.' } }`>> <<ni 'setup.AdvMedkit' setup.Medkit `{ name: "Advanced medkit", desc: "<h2>Medkit</h2><h3>Effect</h3><p>Heals you for <b class=hp>12</b> HP and removes damaging effects</p><h3>Modifiers</h3>Healing" , effect: { code : '<<set _heal = Math.round(12*$healmodifier*randomFloat(0.8,1.2))>><<health _heal>>', desc: 'The medkit heals you for <b class=hp>_heal</b> HP.'}, price: 80 , qual: 'adv' }`>> <<set setup.Tonic = { name: "Tonic", desc: "<h2>Tonic</h2><h3>Type</h3>Combat<h3>Effect</h3><p>Clears stuns<br>Increases damage dealt by 15% for the turn</p>" , effect: {code : '<<set _heat += 15, _playerStun = 0, _blinded = false>><<trigger "skillboxRefresh">>', desc: 'The tonic invigorates you.'}, sit: 'combat', texture: setup.locLoad('tonic'), type: 'consumable', price: 50 , qual: 'common'}>> <<ni 'setup.AdvTonic' setup.Tonic `{ name: "Advanced tonic", desc: "<h2>Tonic</h2><h3>Effect</h3><p>Clears stuns<br>Increases damage dealt by 20% for the turn<br>Grants 1 extra AP</p>" , effect: {code : '<<set _heat += 20, _playerStun = 0, _blinded = false>><<AP -1>><<trigger "skillboxRefresh">>', desc : "The tonic invigorates you.<br><b>+1 AP</b>"}, price: 80 , qual: 'adv'}`>> <<set setup.ShieldBooster = { name: "Shield booster", desc: "- Type -<br>Consumable<br>- Effect -<br>Regain the totally of your shield." , effect: {code : '<<set _shield = $shield>><<trigger "UIupdate">>', desc: 'Your shield quickly regenerates.'}, sit: 'combat', texture: setup.locLoad(''), type: 'consumable', price: 80 , qual: 'adv'}>> /*-------------------------- Transfer keys --------------------------*/ <<set setup.TransferKey = { name: "Transfer key", desc: "<h2>Transfer key</h2><h3>Effect</h3><p>Holds <b class=mo>30</b>, redeemable at any time</p>" , effect: {code : "<<set $money += 30>><<trigger 'UIupdate'>>", desc : '<b class=mo>30</b> earned.'}, texture: setup.locLoad('transkey'), type: 'consumable', sit:'noncombat', qual: 'common' }>> <<ni 'setup.AdvTransferKey' setup.TransferKey `{ desc: "<h2>Transfer key</h2><h3>Effect</h3><p>Holds <b class=mo>60</b>, redeemable at any time</p>" , effect: {code : "<<set $money += 60>><<trigger 'UIupdate'>>" , desc : '<b class=mo>60</b> earned.'}, qual: 'adv' }`>> <<ni 'setup.RandTransferKey' setup.AdvTransferKey `{ name: "Damaged transfer key", desc: "<h2>Transfer key</h2><h3>Effect</h3><p>Slightly damaged, it holds an unknown amount of currency...</p>" , effect: {code : "<<set _randMon = random(20,85), $money += _randMon>><<trigger 'UIupdate'>>", desc : '<b class=mo>_randMon</b> earned.'} }`>> <<ni 'setup.RareTransferKey' setup.TransferKey `{ desc: "<h2>Transfer key</h2><h3>Effect</h3><p>Holds <b class=mo>100</b>, redeemable at any time</p>" , effect: {code : "<<set $money += 100>><<trigger 'UIupdate'>>", desc : '<b class=mo>100</b> earned.'}, qual: 'rare'}`>> <<set setup.DemoCharge = { name: "Demolition charge", desc: "<h2>Demolition charge</h2><h3>Effect</h3><p>Industrial-grade explosives<br>Throwing it in combat would likely kill you.</p>", sit: 'noncombat', type: 'consumable', price: 100 , qual: 'common' }>>
<<widget "fight">> /* Enemy stats*/ <<set $enemy = clone(_args[0])>> <<if _args[1] === "rand">> <<set $MaxEnhealth to Math.round(_args[0].health*$difficulty*randomFloat(0.8,1.2))>> <<set $enemy.startrange to random(1,4)>> <<elseif _args[1] == "champ">> <<set $enemy.AP ++>> <<set $enhealth = Math.round( _args[0].health * $difficulty * 1.5)>> <<elseif typeof _args[1] === 'number'>> <<set $MaxEnhealth = Math.round( _args[1] * _args[0].health * $difficulty)>> <<set $multi = _args[1]>> <<else>> <<set $MaxEnhealth = Math.round( _args[0].health * $difficulty)>> <</if>> /* Adds to seen enemies*/ <<set $hasFought.pushUnique($enemy.name)>> /*--------------------------- Affix system --------------------------*/ /*<<applyAffix 'oninit'>> <<applyAffix 'ondamage'>> <<if !$enemy.ondeath>> <<applyAffix 'ondeath'>> <</if>>*/ /*-------------------------- Victory passage ------------------------*/ <<if _args[2]>> <<set $prev = _args[2]>> <</if>> <</widget>>
/*----------------------------Enemies--------------------------------*/ /* <<set setup.EnemyModel = { name: 'string', behav: 'string', health: null, type: 'string', texture: $localLoad ? "url" : "url", skill: [{name: 'string'}], AP: null, startrange: random(1,4), desc: ['string'], flavor : 'short description for splashscreen', ondeath: ['string'], ondamage: ['string'], plating: number, loot: [], }>> */ /* ---------------------------- Bugs ------------------------------- */ <<set setup.CyberBug = { name: "Cyber bug", behav: "CBbehav", health: 60, type: 'Meca', texture: $localLoad ? "media/cyberbug.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1040753720901779497/cyberbug2.png", AP: 2, startrange: 2, desc: ["The cybernetic scarab rushes toward you with a sharp screech.","The scarabs advance menacingly in your direction.", "The scarabs stands on its hind legs in an attempt to intimidate you."], flavor : 'The humble cyber bug roams the depths in search of organic material.', ondeath: 'The destroyed insect twitches as thick lubricant escapes its body.'}>> <<ni 'setup.AlphaBug' setup.CyberBug `{ name: "Alpha bug", health: 90, texture : $localLoad ? "media/alphabug.png" : 'https://cdn.discordapp.com/attachments/949715863479672913/1047137499123830814/alphabug.png', AP : 3, desc: "<<= $hasFought.includes('Cyber bug')? 'The bug looks bulkier than those you encountered before, more aggressive as well.' : 'The large scarab rushes toward you with a sharp screech.'>>", flavor : 'Bigger than the average cyber bug, this one seems especially aggressive.' }`>> <<set setup.Gregor = { name: "Gregor", behav: "Gregorbehav", health: 65, type: 'Meca', AP: 3, startrange: 2, desc: ["The mechanical bugs squares up, undeterred."] }>> /* ---------------------------- Isopod ----------------------------- */ <<set setup.Isobot = { name: "Isobot", behav: "IsobotBehav", health: 80, plating : 2, type: 'Meca', texture: $localLoad ? "" : "", skill: [{name : 'Plating', desc : 'Incoming damage is reduced by 2.'}], AP: 2, desc: [''], flavor : '' }>> /* ---------------------------- Mom bug ---------------------------- */ <<set setup.MomBug = { name: "CyberBugMother", behav: "MBbehav", health: 100, type: 'Meca', texture: $localLoad ? "media/mombug.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1041049434160640010/mombug.png", skill: [ {name : 'Brood mother', desc : 'Releases a swarm of smaller enemies on death.'}, {name : 'Self repair', desc : 'Able to heal itself in combat.'} ], AP: 3, startrange: 2, desc: ["The large scarab stays at a distance while the swarm buzzes around it."], flavor : 'The large insect is both the queen and the hive to its mechanical swarm.'}>> /* ---------------------------- War dog ---------------------------- */ <<set setup.RabidDog = { name: "War dog", behav: "Dogbehav", health: 55, type: 'Meca', texture: $localLoad ? "media/dog.png" : "https://cdn.discordapp.com/attachments/937698164604022805/1044237539898294272/dog.png", AP: 2, startrange: 1, flavor : 'Built for war, these now roam the underworld carrying out a never ending duty.', desc: ["A rabid dog has taken interest in your meat.","The rabid dogs rush toward you."] }>> /* Thugs ------------------------------------------------------------*/ <<set setup.Thug = { name: "Thug", behav: "Thugbehav", health: 75, AP: 2, startrange: 2, desc: ["A menacing character with an iron bar, he wants your parts.","A large individual with extensive face tattoos stands in your way, club in hand.","A ragged thug comes out of a adjoining street, iron bar in hand."] }>> <<set setup.RifleThug = { name: "RifleThug", behav: "RTbehav", health: 90, AP: 2, startrange: 3, desc: ["A one-eyed man with a rifle. On the older side for a street thug."] }>> <<set setup.Efi = { name: "Efi", behav: "TBbehav", health: 90, loot: [setup.EfisArm, setup.Tonic], AP: 2, startrange: 2, desc: ["A woman with an augmented arm and face tattoos. Certainly belongs to some local gang."], ondeath: 'The woman collapses from her injuries.'}>> <<set setup.ThugBrawler = { name: "ThugBrawler", behav: "TBbehav", health: 75, AP: 2, startrange: 2, desc: ["A female thug with a club and an augmented arm."] }>> /* ------------------------- Rifle bots -----------------------------*/ <<ni 'setup.RifleBot' `{ name: "RifleBot", behav: "RifleBotBehav", health: 120, AP: 2, type: 'Meca', skill: [ {name : 'Take aim', desc : 'Aiming increases ranges damage.'} ], startrange: 3, desc: ["A slender robot carrying a rifle."], flavor : 'Former combat robots were quickly re-affected to securizing the depths.', loot: [setup.AimingMod, setup.AdvAimingMod, setup.ScrapRifle, setup.AdaptAim]}`>> <<ni 'setup.MarksBot' setup.RifleBot `{ name: "MarksBot", health: 180, AP: 3, startrange: 3, desc: ["A shot grazes you. A tall robot with a visor and a long rifle stands up ahead."], loot: [setup.RareAimingMod, setup.AdvAimingMod, setup.Rifle] }`>> /* ------------------------- Brawl bots -----------------------------*/ <<ni 'setup.BrawlBot' `{ name: "BrawlBot", behav: "BBbehav", type: 'Meca', texture: $localLoad ? "media/brawlbot.png" : "https://cdn.discordapp.com/attachments/937698164604022805/1043619939086508154/brawlbot.png", ondamage: "<<set $enemy.DMGresist += 2>>", skill: [ {name : 'Adaptative armor', desc : 'Damage taken increases resistance'} ], health: 220, AP: 3, startrange: 2, desc: ["The behemoth of a robot charges you."], flavor : 'Punch-out time.', loot: [setup.AdvCQCMod, setup.AdvStackOverflow]}`>> <<ni 'setup.Cleaner' setup.BrawlBot `{ name: "Cleaner", health: 350, startrange: 3, desc: ["The massive robot advances toward you."], loot: [setup.RareCQCMod, setup.RareStackOverflow]}`>> <<set setup.SentryBot = { name: "SentryBot", behav: "SBbehav", type: 'Meca', texture : $localLoad ? "media/turret.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1049374599504203826/turret.png", health: 150, AP: 3, startrange: 3, desc: ["An automated sentry stands before you."], loot: [setup.Plating, setup.AdvPlating, setup.ConBlast, setup.AdvConBlast]}>> <<set setup.Boss = { name: "Boss", behav: "Bossbehav", type: 'Meca', health: 220, AP: 4, startrange: 3, desc: ["A tall and slender bot is waiting for you. A long revolver hangs in a hip-hoster at its side."] }>> <<set setup.CBSwarm = { name: "CBSwarm", type: "swarm", behav: "CBSbehav", health: 250, type: 'Meca', AP: 4, startrange: 2, desc: ["A wriggling swarm of robotic scarabs is headed toward you.<br>It seems aggressive."] }>> <<set setup.HeadHunter = { name: "Head hunter", behav: "HHbehav", health: 180, AP: 4, ondamage: "<<if !_enstun && random(1,6) === 6>><<set $enemy.block++>><p>The assassin blocks at the last second.</p><</if>>", texture: $localLoad ? "media/assassin.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1041100438575005747/assassin.png", skill: [ {name : 'Lightning reflexes', desc : 'Has a chance to block incoming attacks.'} ], flavor : "The target's on your back now.", startrange: 4, desc: ["A highly enhanced assassin, she wants your head it seems."] }>> <<set setup.Millipede = { name: "Millipede", behav: "Millibehav", health: 120, type: 'Meca', texture: $localLoad ? "media/milipede.png" : "https://cdn.discordapp.com/attachments/937698164604022805/1044237539545993286/milipede.png", AP: 3, startrange: 2, desc: ["The winding insect scuttles toward you."], flavor : "These have acquired a reputation of vicious killers.", loot: 'setup.RareUpgrades.random()'}>> <<set setup.MinorMillipede = { name: "Minor millipede", behav: "MinorMilliBehav", health: 40, type: 'Meca', AP: 2, startrange: 2, desc: ["The insect's long segmented body emerges from a dark crevice."] }>> <<set setup.RiotBot = { name: "RiotBot", behav: "RBbehav", type: 'Meca', health: 150, AP: 3, startrange: 1, desc: ["An armored robot carrying a shield and a baton."] }>> /* ------------------------- Automatons ---------------------------- */ <<ni 'setup.Auto' `{ name: "Automaton", behav: "Automatonbehav", health: 90, type: 'Meca', texture: $localLoad ? "media/automaton.png" : 'https://cdn.discordapp.com/attachments/949715863479672913/1041851307838935151/automaton.png', skill: [ {name : 'Awakening protocol', desc : 'Automatons gradually gain more AP.'}, {name : 'Unstable core', desc : 'Automatons explode on death.'} ], AP: 1, startrange: 2, desc: "<<set $AutoAware = true>>The plain automaton turns toward you with a mechanical jerk.", flavor : 'The automaton twitches in an unnatural fashion.', ondeath: "The mechanical skeleton suddently explodes<<if _range == 1>>, <<DMG 1 20>><<elseif _range == 2>>, <<DMG 1 10>><</if>>."}`>> <<ni 'setup.AutoDuo' setup.Auto `{ name: "AutoDuo", health: 200, AP: 3, desc: ["Two plain automatons."] }`>> <<set setup.RunAI = { name: "RunAI", behav: "RAbehav", health: 400, type: 'Meca', texture: $localLoad ? "media/runAI.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1041835233017872384/runAI.png", AP: 3, ondamage: "<<if random(1,4) === 4 && _range lte 2>><<set _acid += random(2,4)>><p>Corrosive fluid shoots toward you from the open wound.</p><</if>>", skill: [ {name : 'Caustic blood', desc : 'Close range attacks might coat the attacker in acid.'}, {name : 'Runaway protocol', desc : 'Gradually gains AP.'} ], startrange: 3, desc: ["The octopus-like machine squirms and wriggles with increasing activity."] }>> <<set setup.Overseer = { name: "Overseer", behav: "OverseerBehav", health: 200, type: 'Meca', texture: $localLoad ? "media/overseer.png" : "https://cdn.discordapp.com/attachments/937698164604022805/1043637332647092234/overseer.png", skill: [ {name : 'Drone master', desc : 'Can deploy up to 3 drones'} ], AP: 2, startrange: 4, flavor : 'The Lord of the Drones.', desc: ["An impossibly tall robot stands before you. Dormant drones hang at its sides."], loot: [setup.CombatDrone, setup.HealerDrone, setup.WeaponsSpecialist]}>> <<set setup.TrDummy = { name: "Training dummy", behav: "DummyBehav", health: 2000, texture: $localLoad ? "media/tdummy.png" : "https://cdn.discordapp.com/attachments/949715863479672913/1049374599164481647/tdummy.png", AP: 1, startrange: 2, flavor : ' Training time! ', desc: ["The training dummy stands before you motionless."]}>> <<set $Randomomon = { name: "Randomomon", health: 350, type: 'Meca', AP: 5, startrange: 3, desc: "Disparate mechanical parts have fused and taken a life of their own in the darkness." }>> <<set setup.randomBehav to ["CBSwarmBehav","CyberBugBehav","RifleBotBehav","SentryBotBehav","BrawlBotBehav","BossBehav","RiotBotBehav","RunAIBehav","RabidDogBehav","MBbehav"]>> /* Enemies array, unused for now */ <<set setup.Enemies = [ setup.CyberBug, setup.RabidDog, setup.Thug, setup.RifleThug, setup.ThugBrawler, setup.RifleBot, setup.MarksBot, setup.SentryBot, setup.BrawlBot , setup.Boss, setup.CBSwarm, setup.HeadHunter, setup.RiotBot, setup.RunAI]>>
<<if _range gt 1>> <<divider `_range gt 2 ? 'doubleback' : 'moveback'`>> <p> The robotic animal rushes toward you. </p> <<range -2>><<set _buff = 0>> <<else>> <<divider 'enemy'>> <<if _action === 1 && _buff !== 0>> <p> The mechanical dog latches on with its powerful jaws, <<DMG 1 8>>. <<set _buff = 1>> </p> <<elseif _buff>> <p> The robot's metal teeth rend your flesh, <<DMG 1 12>>. </p> <<else>> <p> The dog bites you, <<DMG 1 7>>. </p> <</if>> <</if>>
<<widget "Victory">> <<clear>> <<if $health gt 0 && _vic>> <<set $surprise = 0>> /* Resets active drone to active by default */ <<for _drone range _activeDrones>> <<set _drone.on = true>> <</for>> <<replace "#CombatUI, #next">><</replace>> <<append "#fight">> <<a "Victory!" id 1 goto $prev>> <<if $enemy.type === 'Meca'>> <<run $(document).one(':passageend', function(){ $('#content').wiki('<<scrap>>'); })>> <</if>> <</a>> <</append>> <<run $('#fight').stop().animate({ scrollTop: $('#fight')[0].scrollHeight}, 800);>> <</if>> <</widget>>
<<widget "itemget">> <<if _args[0].type?.includes('frame')>> <<equip _args[0]>> <<trigger 'UIupdate'>> <<elseif _args[0].type?.includes('weapon')>> <<if $weapons.length+(_args[0].size? _args[0].size : 1) gt $weaponcapacity>> <<set _args[0].dir = '$storage['+$storage.length+']', $storage.push(_args[0])>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$weapons['+$weapons.length+']'>> <<set $weapons.push(_args[0])>> <</if>> <<elseif _args[0].type?.includes('drone')>> <<if $drones.length+(_args[0].size? _args[0].size : 1) gt $dronecapacity>> <<set _args[0].dir = '$storage['+$storage.length+']', $storage.push(_args[0])>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$drones['+$drones.length+']'>> <<set $drones.push(_args[0])>> <</if>> <<elseif _args[0].type is "ammo" and $ammotype !== "None">> <<set _args[0].dir = '$storage['+$storage.length+']'>> <<set $storage.push(_args[0])>> <<elseif ['key', 'consumable'].includes(_args[0].type)>> <<set $player.inventory.push(_args[0])>> <<else>> <<if $equip.length gte $capacity>> <<set _args[0].dir = '$storage['+$storage.length+']'>> <<set $storage.push(_args[0])>> <<else>> <<equip _args[0]>> <<set _args[0].dir = '$equip['+$equip.length+']'>> <<set $equip.push(_args[0])>> <</if>> <</if>> <</widget>>
<<set setup.ItemAffixes = [ {name: 'Powerful', condition : 'item.damage', effect : 'item.damage ++', desc : ' <b>Powerful</b> : +1 damage' }, {name: 'Lucky', condition : 'item.ap', effect : { preAttack : '<<if random(1,10) === 10>><<set _AP++>><p class small>Free action!</p><</if>>'}, desc : ' <b>Lucky</b> : actions have a 10% chance not to consume AP.' }, {name: 'Twin', condition : 'item.size !== 2 && (item.num === 1 || item.num === undefined)', effect : "item.num = item.num ? item.num*2 : 2;" + "item.size = item.size ? item.size*2 : 2;" + "item.price *= 1.5 ;" + "item.qual += ' s2';" + "item.effect = item.effect ? item.effect+item.effect : null;", desc : " <b>Twin</b> : The item's size, number of attacks and effects are doubled." }, {name: 'Bonus', condition : 'item.num > 1', effect : "item.num ++", desc : " <b>Bonus</b> : +1 attack." }, {name: 'Critical', condition : 'item.damage', effect : "item.crit ? item.crit *= 1.25 : item.crit = 1.875;", desc : " <b>Critical</b> : Increases critical damage by 25%." }, {name: 'x2', condition : 'item.damage', effect : "item.modif ? item.modif.DMGresist = -100 : item.modif = {DMGresist : -100};" + "item.damage *= 2;", desc : " <b class='red'>x2</b> : Deal double damage, take double damage." }, {name: 'x3', condition : 'item.damage', effect : "item.modif ? item.modif.DMGresist = -200 : item.modif = {DMGresist : -200};" + "item.damage *= 3;", desc : " <b class='red'>x3</b> : Deal triple damage, take triple damage." }, {name: 'Cheap', condition : 'item.price', effect : "item.price *= 0.5", desc : " <b>Cheap</b> : Item is half price." }, {name: 'Premium', condition : 'item.price', effect : "item.price *= 2", desc : " <b>Cheap</b> : Costs twice as much." }, {name: 'Runaway', condition : 'item.num', effect : "item.num = 'random(0,10)===10?'+(item.num+1)+':'+item.num+';'", desc : " <b>Runaway</b> : 10% chance for an extra attack" }, {name: 'Caustic', condition : 'item.damage', effect : {effect : '<<set $enemy.DoT.acid += _num>>'+'<p class="small">Caustic : +<b class="acid">_num acid</b></p>'}, desc : " <b>Caustic</b> : Hits apply <b class='acid'>acid</b> to the enemy" }, {name: 'Potent', condition : 'item.damage', effect : {effect : '<<if random(0,10)===10>><<stun>><</if>>'}, desc : " <b>Potent</b> : Attacks have a 10% chance to stun the enemy." }, {name: 'Healthy', condition : 'item.type === "passive"', effect : "item.modif.MaxHealth = 4, item.modif.health = 4", desc : " <b>Healthy</b> : Increases <b class='hp'>HP</b> by 4." }, {name: 'Charged', condition : 'item.type === "passive"', effect : "item.modif.shield = 3", desc : " <b>Healthy</b> : Increases <b class='sh'>shield</b> by 3." }, {name: 'Overcharged', condition : '!item.damage && item.type !== "passive"', effect : {effect : '<<set _shield += 5>><<trigger "UIupdate">>'+'<p class="small">Overcharged : +<b class="sh"> 5 </b>shield</p>'}, desc : " <b>Overcharged</b> : Restores 5 shield on use." }, {name: 'Restorative', condition : '!item.damage && item.type !== "passive"', effect : {effect : '<<set $health += 5>><<trigger "UIupdate">>'+'<p class="small">Restorative : +<b class="hp"> 5 </b>HP</p>'}, desc : " <b>Restorative</b> : Restores 5 health on use." }, {name: 'Long reach', condition : 'item.rmax', effect : 'item.rmax ++', desc : " <b>Long reach</b> : Increases max range by 1." }, {name: 'Life leech', condition : 'item.damage', effect : {effect : '<<if $health lt $MaxHealth>><<health 2>><p class="small">Life leech : +<b class="hp"> 2 </b>HP</p><</if>>'}, desc : " <b>Life leech</b> : Restores 2 health on attack." }, {name: 'Killshot', condition : 'item.damage', effect : {preAttack : "<<once 'passage' `_item.name+'on'`>><<set _heat += 50>><p class='small'>Killshot!</p><</once>>", effect : "<<once 'passage' `_item.name+'off'`>><<set _heat -= 50>><</once>>"}, desc : " <b>Killshot</b> : The first attack this combat deals +50% damage." } ]>> /* Affix function */ <<set setup.applyAffix = function(item, affix) { if (eval(affix.condition)){ if (!item.name.includes(affix.name)){ item.name = affix.name + ' ' + item.name.toLowerCase(); } item.desc.Affix ? item.desc.Affix += '<br>'+affix.desc : item.desc.Affix = affix.desc; if (typeof affix.effect === 'object'){ for (const key in affix.effect){ item[key] ? item[key] += affix.effect[key] : item[key] = affix.effect[key]; } } else { eval(affix.effect); } } return item;}>> <<set setup.addAffix = function(itemref, affix){ let item = clone(itemref), st = State.temporary; if (affix === undefined) { setup.applyAffix(item, setup.ItemAffixes.random()) } else if (typeof affix === 'number') { for (let i = 0; i < affix; i++){ setup.applyAffix(item, setup.ItemAffixes.random()) } } else if (typeof affix === 'string'){ setup.applyAffix(item, setup.ItemAffixes.find(aff => aff.name == affix)); } else if (typeof affix === 'object'){ affix.forEach( aff => {setup.applyAffix(item,setup.ItemAffixes.find(item => item.name == aff))}); } item.dir = '$rooms['+State.variables.pos+'].item'; return item; }>>
The wide covered street stretches in front of you, bustling with activity. Random event/nothing <<keepgoing>>
The streets lead you to a domed space, similar to that of the surface hub but much smaller. From here, more paths stretch in every direction.
Across the steets from you is a covered garden. The sight of greenery is a rare one in Ibadan. The atmosphere inside the garden is humid and tropical, natural light shines down from a hole in the domed ceiling.
A bustling market-place fills the wide street in front of you. Stalls of all kinds offer a seemingly endless choice of merchandise. MarketEvent <<keepgoing>>
<<if $AutoAware>> <p> Another strange automaton lies on the ground in front of you. Its metal chest is caved in and its limbs torn off. </p> <<else>> <p> A heavily damaged automaton lies on the ground. <br> Its design is unlike any robot you have encountered, it is built crudely from mismatched parts and components. </p> <</if>> <<adel "See what you can salvage" id 1>> <<set setup.editRoom( {type : 'Empty room', content : 'The destroyed automaton lies motionless in the shadows.' )>> <<app '#content'>> <p> Searching the metallic carcass yields a handful of scraps. <<scrap `random(10,25)`>> </p> <<set $AutoAware = true>> <</adel>>
The streets become gradually tighter, the lighting rarer. Irregular housing blocks
<p> A breeze of fresher air pushes you to look up. In the darkness above, a faint amber light seems to illuminate a small platform, high above the ground.</p> <<if $grapple>> <<adel 'Grapple up there.' id 1>> <<app '#content'>> <p> The integrated grapple lets you pull yourself up to the elevated surface. The narrow ledge leads to a grimy tunnel... </p> <<a 'Follow it' id 1 goto 'SecretRoom'>><</a>> <</adel>> <</if>>
<<divider 'drone'>> <p> <<= _currentDrone.name>>: <br> <<if !_currentDrone.on>> This drone is inactive. <<elseif $health lt $MaxHealth >> <<set _heal = Math.round(6*$droneaffinity*$healmodifier*randomFloat(0.8,1.2))>> <<if _heal gt $MaxHealth - $health>> <<set _heal = $MaxHealth - $health>> <</if>> <<health _heal>> The drone heals you for <b style="color:var(--hp);">_heal HP</b>. <<elseif _block lt $maxBlock>> The drone grants you <div class=block>1</div> block. <<set _block ++>> <<trigger "UIupdate">> <<else>> The drone hovers silently. <</if>> </p>
People gather around a few decrepit stalls at a crossing. They watch look at you with defiance. <<keepgoing "Leave">> <<linkreplace "Take a closer look.">>The crowd mutters but lets you browse the merchandise of the street vendors... <</linkreplace>>
<<widget 'consume'>> <<set _cond = false>> <<if _args[0].condition === undefined>> /* No condition, always usable*/ <<set _cond = true>> <<else>> /* Evaluate item condition */ <<= '<<if '+_args[0].condition.code+'>><<set _cond = true>><</if>>'>> <</if>> <<= _args[0].desc>> /* Item desc, should always be there ...*/ /* Use link */ <h3>Use</h3> <<if _cond === false>> /* Display condition not met message */ <b class='red'><<= _args[0].condition.desc>></b> <<elseif _args[0].sit === 'combat' && passage() !== 'Combat'>> <b class='red'>This item can only be used in combat.</b> <<elseif _cond>> /* Condition is met */ <<adel 'Use _args[0].name' key 'y'>> /* Run effect code */ <<run $.wiki(_args[0].effect.code);>> /* Remove item */ <<set $player.inventory.delete(_args[0])>> /* Display description */ <<if _args[0].sit === 'combat'>> /* Display in fight window */ <<append '#fight'>> <p><<= _args[0].effect.desc>></p> <</append>> <<run Dialog.close();>> <<else>> /* Display in dialog */ <<replace '#ui-dialog-body'>> <p><<= _args[0].effect.desc>></p> <</replace>> <</if>> /* Update inventory */ <<trigger 'consume'>> <</adel>> <</if>> <</widget>>
<<a 'Leave.' goto 'Game'>><</a>> Inner network access.
<<fight `either($RifleBot, setup.RiotBot, setup.SentryBot)` "rand">> In the distance, you see a <<= $enemy>>, it hasn't noticed you yet... <<link "Attack it!" "Lvl3Combat">> <<set $surprise to +1>> <<set $turn to "You manage to sneak up on your opponent.">> <</link>> <<keepgoing "Leave it be.">>
<p> An old crate sits in a corner of the room, half buried under dusty rubble. The paint flakes off from the corroded metal. </p> <img src='https://cdn.discordapp.com/attachments/949715863479672913/993157741298335855/crate.png'> <<adel "See what's inside" id 1>> <<set setup.editRoom( {type: 'Empty room', content: 'The corroded crate lies toppled over on the bare ground.'} )>> <<app '#content'>> The crate seems empty. As you pull your hand out, you feel a sharp sting. Some long, wriggling creature was waiting at the bottom. You lose <b class=red>6</b> HP. <<health -6>> <<a 'Fight it!' id 1>> <<fight setup.MinorMillipede>> <<goto 'Combat'>> <</a>> <</adel>>
<p> A square container catches your attention. </p> <img @src="$localLoad ? 'media/wepcrate.png' : 'https://malifaciousgames.neocities.org/media/wepcrate.png'" style='max-width: 15em;'> <<adel "Examine it" id 1>> <<set _loot = setup.Weapons.random()>> <<set setup.editRoom( {type: 'Loot', content: 'The open weapon case lies on the ground.', item : _loot} )>> <<app>> <p> The reinforced box opens without much difficulty and reveals a weaponn. </p> <<itemloot _loot>> <</adel>>
<<if $enhealth lt (20*$difficulty) and _talk is 1>> <<set _talk -->> <<set _talked to true>> <</if>> <<if _talked>> <p> <em>Hey, hear me out! <br> We don't have to do that, no one wants to die here. We stay out of your way, you stay out of ours. <br> Got a deal?</em> </p> <div class="EvenSpace" id='choice'> <<a "Yeah, we're good." key settings.yes>> <<set _vic = true>> <<rep>> '#choice'>><<Victory>> <</a>> <<a "Nah, I'm killing you for sure." key settings.no>> <<rep '#choice'>><<EnemyTurn>> <</a>> </div> <<elseif _grap && _action === 2>> <<divider 'enemy'>> <p> She follows up with a punch, <<DMG 1 9>>. </p> <<set _grap = false>> <<elseif _range === 2 and _enemyuse>> <<divider 'enemy'>> <<set _enemyuse -->><<set _blinded to true>> <p> The woman throws a hand-made grenade at you, <<DMG 1 20>>. <<if !_block>> <br>You are STUNNED. <<set _playerStun ++>> <</if>> </p> <<elseif _range === 1 and _enemyuse>> <<divider 'moveback'>> <p> The thugs takes a quick step back. </p> <<range 1>> <<elseif _range gt 2>> <<divider 'movefor'>> <p> The woman pulls you with her <b>grapple arm</b>, <<DMG 1 5>>. </p> <<set _grap = true>> <<range -3>> <<elseif _range === 2>> <<divider 'movefor'>> <p> The thug advances toward you. </p> <<range -1>> <<else>> <<divider 'enemy'>> <p> <<= either("The woman hits you with her club, <<DMG 1 12>>.","She punches you with her augmented arm, <<DMG 1 9>>.")>> </p> <</if>>
<<if _range === 1>> <<skill setup.Gunblade.slashicon 'Gunblade slash'>> <<AP 1>> <<append "#fight">> <p> The slash <<EnDMG 1 16 `[$weaponsmodifier,$cqcmodifier]`>> </p> <</append>> <</skill>> <<else>> <<skill setup.Gunblade 'Fire gun-blade'>> <<AP 1>> <<append "#fight">> <p> The shot <<EnDMG 1 14 `[$weaponsmodifier,_rangemodifier]`>> <<ammo>> </p> <</append>> <</skill>> <</if>>
<<if $enhealth lt (25*$difficulty) and _talk is 1>> <<set _talk -->> <<set _talked to true>> <</if>> <<if $disarmed is true and _talk is 1>> <<set _talk -->> <<set _talked to true>> <</if>> <<if _talked is true>> <<set _range ++>><<if _range gt 3>><<set _range to 3>><</if>> The man takes a step back, protecting himself. <br> <em>Hey listen, wanna call it off? <br> Didn't know you were that tough, took you for an easy target. I don't wanna die bud, got a family to feed that's all. <br> Wanna drop it?</em> <br> <br> <div class="EvenSpace"> <<link "Yeah, we're good.">> <<set _spared to true>> <<Victory>> <</link>> <<link "Nah, I'm killing you for sure.">> <<EnemyTurn>> <</link>> </div> <<elseif _range is 3>> The thug advances toward you. <<set _range -->> <<elseif _range is 2 and _enemyuse is 1>> <<set _enemyuse -->> The man throws a hand-made grenade at you, dealing <<DMG 1 25>> damage. <<elseif _range is 2>> The thug shoots you with a makeshift pistol, dealing <<DMG 1 9>> damage. <<elseif _disarmed is true>> Your opponent punches you for <<DMG 1 4>>. <<else>> Your opponent hits you with a metal bar, dealing <<DMG 1 12>> damage. <</if>>
<<set _crossDesc = [ "Your steps echo in the vast space ahead.<<lights 0>>", "The ceiling above opens on a wide open well, reaching up toward the higher levels.", "Corroded metal columns tower under the high vaulted ceiling in the largest room you have seen yet.<<lights 5>>", "Faint rays of natural light pour down from the damaged ceiling.<<lights 0>>", ]; _crossDesc.custom = 80; _crossDesc.custom = 10; _genDesc = [ "The weakened ceiling has collapsed in places, cables hang loose above your head.<<lights 0>>", 'The long winding shell of a mechanical millipede lies in a corner.', 'The narrow room is filled with the stench of used machine oil.<<lights 1>>', 'You hear the sound of trickling water before smelling the putrid stench of sewage.', 'Winding pipes spread in every direction along the walls, supplying the busy metropolis above.' ], _bendDesc = [ 'The corridor makes a sharp bend.', 'A collapsed wall lets you push further into the underground maze.', 'The dark path takes a turn.' ]; _bendDesc.custom = 25; _bendDesc.gen = 40; _endDesc = [ 'The room ahead is a dead-end.', 'The path leads you to a small room littered with debris.', 'This part of the underground labyrinth ends on a dark dead-end.', 'The small space ahead is crowded with tall metal conduits.' ]; _endDesc.custom = 60; _endDesc.gen = 15; >> <<run _descGiver = (room, descArray) => { if (room.desc === undefined) { const rand = random(100); if (rand lt (descArray.custom ?? 0)) { room.desc = descArray.random(); } else if (rand lt (descArray.custom ?? 0)+(descArray.gen ?? 0)){ room.desc = _genDesc.random(); } } }>> /* Set room geometry and fitting description */ <<run _spareRooms = [], _formerCorridors = []; $rooms.forEach(room => { if (typeof room === 'object') { const con = room.connect; /* Array of connections */ if (con.length === 4) { room.geometry = 'cross'; _descGiver(room, _crossDesc); } else if (con.length === 3) { room.geometry = 't'; _descGiver(room, _genDesc); } else if (con.includesAll('connectUp','connectDown') || con.includesAll('connectRight','connectLeft')) { _formerCorridors.push(clone(room)); room.type = 'corridor'; room.geometry = (con.includesAll('connectUp','connectDown') ? 'vert' : 'hori') + 'straight'; } else if (con.length === 2) { room.geometry = 'bend'; _descGiver(room, _bendDesc); } else { room.geometry = 'deadend'; _descGiver(room, _endDesc); } } })>> /* Find empty rooms for substitution */ <<run $rooms.forEach(( r, i) => { if(r.type === 'Empty room'){ _spareRooms.push(r.index); } if(r.type === 'corridor'){ if(r.geometry === 'vertstraight'){ $rooms[ setup.traverseCorridor(i, $MaxX)].possible.delete(i); $rooms[ setup.traverseCorridor(i, -$MaxX)].possible.delete(i); $rooms[ setup.traverseCorridor(i, -$MaxX)].possible.push( setup.traverseCorridor(i,$MaxX) ); $rooms[ setup.traverseCorridor(i, $MaxX)].possible.push( setup.traverseCorridor(i,-$MaxX) ); } else { /* Horizontal */ $rooms[ setup.traverseCorridor(i, 1)].possible.delete(i); $rooms[ setup.traverseCorridor(i, -1)].possible.delete(i); $rooms[ setup.traverseCorridor(i, -1)].possible.push( setup.traverseCorridor(i, 1) ); $rooms[ setup.traverseCorridor(i, 1)].possible.push( setup.traverseCorridor(i,-1) ); } } }); /* Rooms that became corridors are pushed to remaining empty rooms */ _formerCorridors.forEach( r => { const i = _spareRooms.pluck(); $rooms[i].type = r.type; $rooms[i].content = r.content; }); /* Find starting position! */ $pos = $rooms.indexOf($rooms.find( r => r.type === 'Start'))>> /* Loading timer end */ <<run console.log('Generation took: ' +(new Date().getTime() - _time)) + ' ms.'>>
<<include 'item affixes'>> /* Weapons */ <<set setup.RotaryCannon = { name: "Rotary cannon", ap: 2, damage: 8, num: 6, modifiers: ['$weaponsmodifier', '_rangemodifier'], prompt: 'The air fills with a deafening whir.<br>The torrent of lead', effect: '<<ammo>>', desc: { flavor : 'A heavy weapon capable of incredible firepower.', Size : 2, Range : 'Medium, long', Modifiers : 'Ranged, weapon affinity, ammo type', AP_cost : 2}, texture: setup.locLoad('rotarycannon'), icon: setup.locLoad('rotaryicon'), price: 200 , qual: 'rare s2', type: "weapon" , rmin: 3 , size: 2 }>> /*------------------------------ Sword ------------------------------*/ <<set setup.Sword = { name: "Sword", damage: 15, modifiers: '$cqcmodifier', prompt: 'The slash', desc: {flavor: 'Crude and timeless.<br>Cannot be interfaced with...', Range : 'Close quarters', Modifiers : 'CQC'}, texture: setup.locLoad('sword'), icon: setup.locLoad('swordicon'), price: 100 , qual: 'common', type: "weapon" , rmax: 1 }>> /*----------------------------- Katana ------------------------------*/ <<ni 'setup.Katana' setup.Sword `{ name: "Katana", skill: "Katana", desc : {flavor : "The strange sword can be interfaced with, which is highly unusual for melee weapons.<br>Likely custom-made for its previous owner...", Damage : "<b>Close quarters</b> : 25"+ "<br><b>Short range</b> : 20", Modifiers : "CQC, weapon affinity", Effect : "Attacking at short range cause you to dash forward." }, texture: setup.locLoad('katana'), icon: setup.locLoad('katanaslash'), price: 200 , qual: 'spec', rmax: 2}`>> /* ---------------------------- Grenades ----------------------------*/ <<ni 'setup.HEGrenade' `{ name: "High explosives grenade", charge: ['HEgrenade', true, 1], noMessage : 'No grenades left.', damage: 25, modifiers : '$blastmodifier', skillname : 'Throw grenade', prompt: 'The explosion', desc : {flavor : "<p>A handheld explosive charge, crude but effective</p>", Range : "Short, medium.", Modifiers : "Explosive damage, extra uses"}, texture: setup.locLoad('grenade'), icon: setup.locLoad('explosion'), price: 100 , qual: 'common', type: "weapon" , modif : {HEgrenade : 1}, rmin: 2 , rmax: 3}`>> <<ni 'setup.StunGrenade' setup.HEGrenade `{ name: "Stun grenade", charge : ['stungrenade', true, 1], prompt: 'The grenade explodes with a blinding flash and', damage: 8, effect: '<<stun 2>>', desc : {flavor : "<p>Excels at blinding opponents.</p>", Range : "Short, medium.", Effect : "Stuns: 2", Modifiers : "Explosive damage, extra uses"}, icon: setup.locLoad('flashbang'), modif : { stungrenade : 1}}`>> <<ni 'setup.AcidGrenade' setup.HEGrenade `{ name: "Acid grenade", charge : ['acidgrenade', true, 1], damage: 4, skillname: 'Throw acid grenade', prompt: 'The canister ruptures and', effect: ', coating the opponent in acid.<<set $enemy.DoT.acid += 10>>', desc : {flavor : "<p>Filled with a highly corrosive substance.<br>This weapon cannot be interfaced with...</p>", Range : "Short, medium.", Damage : 4, Effect : "Acid: <b class='acid'>10</b>", Modifiers : 'Extra uses'}, modif : {acidgrenade : 1} }`>> /* --------------------------- Revolver -----------------------------*/ <<set setup.Revolver = { name: "Revolver", ap : 1, skillname : 'Fire revolver', prompt : 'The shot', damage : 14, crit : 2, modifiers : ['$weaponsmodifier','_rangemodifier'], effect : "<<ammo>>", desc : {flavor : "A large calibar handgun.", Range : "Short, medium, long.", Critical_modifier : 2 , Modifiers : "Weapon, ranged, ammo type" }, texture: setup.locLoad('revolver'), icon : setup.locLoad('revolvericon'), qual: 'adv', type: 'weapon pistol', price: 140, rmin: 2}>> /* ---------------------------- Pistol ------------------------------*/ <<ni 'setup.Pistol' setup.Revolver `{ name: "Pistol", ap : '_freeshot ? 0 : 1', skillname : 'Fire pistol', skillextra : '<<if _freeshot>><div class="freeaction"/><</if>>', damage : '14-_range', effect : "<<ammo>><<if _freeshot>><<set _freeshot = false>><</if>><<trigger 'skillboxRefresh'>>", crit : 1.5, desc : { flavor : "Used to be the standard issue pistol during the war.", Damage : "<b>Short</b> : 12" + "<br>" + "<b>Medium</b> : 11" + "<br>" + "<b>Long</b> : 10", Modifiers : "Ranged, weapon affinity, ammo type." }, texture: setup.locLoad('pistol'), icon: setup.locLoad('pistolicon'), price: 120}`>> /* --------------------------Pipe pistol ----------------------------*/ <<ni 'setup.PipePistol' setup.Revolver `{ name: "Pipe pistol", skillname : 'Fire pipe pistol', damage : '14-_range*2', modifiers : '_rangemodifier', crit : 1.5, desc : {flavor : "The proud work of an amateur gunsmith.", Range : "Short, medium, long.", Damage : "By range: 10, 8, 6", Modifiers : "Ranged, ammo type" }, texture: setup.locLoad('pipepistol'), icon: setup.locLoad('pipepistolicon'), price: 60 , qual: 'common'}`>> /* --------------------------Scrap rifle ----------------------------*/ <<set setup.ScrapRifle = { name: "Scrap rifle", damage: 14, skillname: 'Fire rifle', prompt : 'You line up your shot which', modifiers : '_rangemodifier', effect: '<<ammo>>', desc : { flavor : "Such a crude weapon cannot be interfaced with...", Range : "Short, medium, long.", Damage : 14, Modifiers : "Ranged, ammo type" }, texture: setup.locLoad('scraprifle'), price: 80 , qual: 'common', type: "weapon", rmin: 2 }>> /* --------------------------- Gunblade -----------------------------*/ <<set setup.Gunblade = { name: "Gun-blade", skill: "Gun-blade", desc : {flavor : "Feels otherworldy...", Damage : "Close quarters: 16 <br>Other ranges: 14", Modifiers : "Close quarters: CQC, weapon affinity<br>Other ranges: Ranged, weapon affinity, ammo type", About : "A tribute to RynGM's <i>Trigaea</i>, by far the best sci-fi Twine game ever made.<br>Give it a try." }, texture: setup.locLoad('gunblade'), icon: setup.locLoad('GBshot'), slashicon: setup.locLoad('GBslash'), dir : 'setup.Gunblade', price: 150 , qual: 'spec', type: "weapon" , stat1: "$gunblade" , modif1: 1}>> /* ---------------------------- Rifle -------------------------------*/ <<set setup.Rifle = { name: "Rifle", skillextra : "<<if _range === 4>><div class='optirange'></div><</if>>", skillname : 'Fire rifle', prompt : 'The precise shot', damage : '5+_range*5', modifiers : ['_rangemodifier', '$weaponsmodifier'], effect : '<<ammo>>', crit : 2 , critChange : 5, desc : {flavor: "A precision rifle most effective at long ranges.", Range : "Short, medium, long", Damage : "<b>Short</b> : 15" + "<br>" + "<b>Medium</b> : 20" + "<br>" + "<b>Long</b> : 25", Modifiers : "Weapon affinity, ranged, ammo type", Critical : '+5% chance, x2 damage' }, texture: setup.locLoad('rifle'), icon: setup.locLoad('rifleicon'), price: 150 , qual: 'adv', type: "weapon" , stat1: "$rifle" , modif1: 1 , rmin: 2 }, setup.Darts = { name: "Darts", skillname : 'Throw darts', damage : '5-_range', modifiers : '_rangemodifier', prompt : 'The darts', effect : '<<set $enemy.DoT.darts += 4-_range>>', desc : {flavor : "Each dart carries thousands of destructive nanomachines which deal damage over time.", Range : "Close, medium", Damage : 3, Effect : "DoT: 3<br>Does not decay.", Modifiers : "Ranged" }, texture: setup.locLoad('dart'), icon: setup.locLoad('dartsicon'), price: 150 , qual: 'adv', type: "weapon" , rmax: 3 }>> <<set setup.Shield = { name: "Shield", skillname : 'Shield up', cond : '_block !== $maxBlock', noMessage : 'Maximum block reached.', prompt : "You take cover behind the heavy shield.<br>+ <div class='block'>1</div> block", effect: "<<set _block ++>><<trigger 'UIupdate,skillboxRefresh'>>", desc: {Effect : 'Grants one block token on use.'}, texture: setup.locLoad('shield'), icon: setup.locLoad('shieldicon'), price: 150 , qual: 'adv', type: "weapon" }>> <<ni 'setup.SMG' `{ name: "SMG", skillname : 'Fire SMG', prompt : 'The sustained fire', num : '5-_range', damage : 7, modifiers : ['$weaponsmodifier', '_rangemodifier'], effect : '<<ammo>>', desc: {flavor : 'The handy submachine gun excels at close range.', Damage: "<b>Short range</b> : 3 x 7" + '<br>' + "<b>Medium range</b> : 2 x 7" + '<br>' + "<b>Long range</b> : 7", Modifiers: "Ranged, weapon affinity, ammo type" }, texture: setup.locLoad('smg'), icon: setup.locLoad('smgicon'), price: 180 , qual: 'adv', type: "weapon" , rmin: 2 }`>> <<ni 'setup.Bullpup' setup.SMG `{ name: "Bullpup", skillname : 'Fire bullpup', damage: 9, num : 2, prompt : 'The quick burst', desc : {flavor : "A compact assault rifle designed for urban campaigns during the Second Federal War." , Range : "Short, medium, long.", Modifiers : "Ranged, weapon affinity, ammo type", Passive_effect : "The first move made each turn is free." }, icon: setup.locLoad('bullpupicon'), texture: setup.locLoad('bullpup'), modif : {freemove : 1} }`>> <<ni 'setup.autopistol' setup.SMG `{ name: "Auto-pistol", skillname : 'Fire pistol', prompt : 'The rain of small caliber rounds', num : '5-_range', damage : '7-_range', modifiers : ['$weaponsmodifier', '_rangemodifier'], effect : '<<ammo>>', desc: {flavor : 'The greatest amount of firepower in the smallest package.', Damage: "<b>Short range</b> : 3 x 6" + '<br>' + "<b>Medium range</b> : 2 x 5" + '<br>' + "<b>Long range</b> : 4", Modifiers: "Ranged, weapon affinity, ammo type" }, texture: setup.locLoad('autopistol'), icon: setup.locLoad(''), price: 120 , qual: 'adv', type: ['weapon','pistol'] , rmin: 2 }`>>
/*Passive items*/ <<set setup.WeaponsSpecialist = { name: "Weapons specialist module", desc: {Effect : 'Increases weapon capacity by 1<br>Increases weapon affinity by 10%'}, texture: setup.locLoad('weapspecialist'), type: "passive" , price: 250 , qual: 'rare', modif : {weaponcapacity : 1, weaponsmodifier : 10} }>> /* Drone interface --------------------------------------------------*/ <<set setup.DroneInterface = { name: "Drone interface", desc: {Effect : 'Increases drone damage by 20%<br>Increases drone affinity by 20%'}, texture: setup.locLoad('droneinterface'), type: "passive" , price: 120 , qual: 'common', modif : {droneDMG : 20, droneaffinity : 20} }>> <<ni 'setup.AdvDroneInterface' setup.DroneInterface `{ name: "Advanced drone interface", desc: {Effect : 'Increases drone damage by 35%<br>Increases drone affinity by 35%'}, price: 200 , qual: 'adv', modif : {droneDMG : 35, droneaffinity : 35}}`>> <<ni 'setup.RareDroneInterface' setup.DroneInterface `{ name: "Rare drone interface", desc: {Effect : 'Increases drone damage by 45%<br>Increases drone affinity by 45%'}, price: 250 , qual: 'rare', mmodif : {droneDMG : 45, droneaffinity : 45}}`>> /* Aiming modules ---------------------------------------------------*/ <<ni 'setup.AimingMod' `{ name: "Aiming module", desc: {Effect : 'Increases ranged damage by 10%'}, texture: setup.locLoad('aimingmodule'), type: "passive" , price: 100 , qual: 'common', modif: {rangemodifier : 10} }`>> <<ni 'setup.AdvAimingMod' setup.AimingMod `{ name: "Advanced aiming module", desc: {Effect : 'Increases ranged damage by 20%'}, price: 150 , qual: 'adv', modif: {rangemodifier : 20} }`>> <<ni 'setup.RareAimingMod' setup.AimingMod `{ name: "Rare aiming module", desc: {Effect : 'Increases ranged damage by 25%'}, price: 200 , qual: 'rare', modif: {rangemodifier : 25} }`>> /* CQC modules ------------------------------------------------------*/ <<ni 'setup.CQCMod' `{ name: "CQC module", desc: {Effect : 'Increases melee damage by 10%'}, texture: setup.locLoad('cqcmod'), type: "passive" , price: 100 , qual: 'common', modif : {cqcmodifier : 10 } }`>> <<ni 'setup.AdvCQCMod' setup.CQCMod `{ name: "Advanced CQC module", desc: {Effect : 'Increases melee damage by 20%'}, price: 150 , qual: 'adv', modif : {cqcmodifier : 20 } }`>> <<ni 'setup.RareCQCMod' setup.CQCMod `{ name: "Rare CQC module", desc: {Effect : 'Increases melee damage by 25%'}, price: 200 , qual: 'rare', modif : {cqcmodifier : 25 } }`>> /* Burst cores ------------------------------------------------------*/ <<set setup.ExtraStorage = { name: "Extra storage", desc: {Effect : 'Limited use items gain 1 extra charge'}, texture: setup.locLoad('extrastorage'), type: "passive" , price: 140 , qual: 'common', modif : {extrause : 0.5 }}>> <<ni 'setup.AdvExtraStorage' setup.ExtraStorage `{ name: "Advanced extra storage", desc: {Effect : 'Charges for limited use items are doubled'}, price: 200 , qual: 'adv', modif : {extrause : 1 }}`>> /* Plating ----------------------------------------------------------*/ <<set setup.Plating = { name: "Plating", desc: {Effect : 'Reduces incoming damage by 5%'}, texture: setup.locLoad('plating'), type: "passive" , price: 100 , qual: 'common', modif: { DMGresist : 5 }}>> <<ni 'setup.AdvPlating' setup.Plating `{ name: "Advanced Plating", desc: {Effect : 'Reduces incoming damage by 10%'}, price: 150 , qual: 'adv', modif: { DMGresist : 10 } }`>> <<ni 'setup.RarePlating' setup.Plating `{ name: "Rare Plating", desc: {Effect : 'Reduces incoming damage by 15%'}, price: 210 , qual: 'rare', modif: { DMGresist : 15 } }`>> /* High explosives --------------------------------------------------*/ <<ni 'setup.HiExplosives' `{ name: "High explosives", desc: {Effect : 'Increases explosive damage by 10%'}, texture: setup.locLoad('hiexp'), type: "passive" , price: 100 , qual: 'common', modif : {blastmodifier : 10} }`>> <<ni 'setup.AdvHiExplosives' setup.HiExplosives `{ name: "Advanced high explosives", desc: {Effect : 'Increases explosive damage by 20%'}, price: 150 , qual: 'adv', modif : {blastmodifier : 20} }`>> <<ni 'setup.RareHiExplosives' setup.HiExplosives `{ name: "Rare high explosives", desc: {Effect : 'Increases explosive damage by 25%'}, price: 200 , qual: 'rare', modif : {blastmodifier : 25} }`>> /* Discharge cores --------------------------------------------------*/ <<set setup.DisCore = { name: "Discharge core", desc: {Effect : 'Increases electric damage by 10%'}, texture: setup.locLoad('discore'), type: "passive" , price: 100 , qual: 'common', modif: { elecmodifier : 10} }>> <<ni 'setup.AdvDisCore' setup.DisCore `{ name: "Advanced discharge core", desc: {Effect : 'Increases electric damage by 20%'}, price: 150 , qual: 'adv', modif: { elecmodifier : 20} }`>> <<ni 'setup.RareDisCore' setup.DisCore `{ name: "Rare discharge core", desc: {Effect : 'Increases electric damage by 25%'}, price: 200 , qual: 'rare', modif: { elecmodifier : 25}}`>> /* ----- Ammunitions ------------------------------------------------*/ <<set setup.ExplosiveRounds = { name: "Explosive rounds", desc: {Effect : 'Ranged attacks deal extra explosive damage'}, texture : setup.locLoad('ammo'), type: "ammo" , price: 180 , qual: 'adv', modif : {ammotype : "Explosive"} }>> <<ni 'setup.ShockRounds' setup.ExplosiveRounds `{ name: "Shock rounds", desc: {Effect : 'Ranged attacks have a chance to stun'}, texture : setup.locLoad('elecammo'), modif : {ammotype : "Shock"} }`>> <<ni 'setup.AcidRounds' setup.ExplosiveRounds `{ name: "Corrosive rounds", desc: {Effect : 'Ranged attacks apply <b class="acid">1</b> acid'}, price: 150 , modif : {ammotype : "Acid"} }`>> /* Escalation modules -----------------------------------------------*/ <<set setup.EscalationMod = { name: "Escalation module", desc: {Effect : 'Adds a 10% chance of dealing an extra attack'}, texture: setup.locLoad('escmod'), type: "passive" , price: 120 , qual: 'common', modif: {allin : 10 } }>> <<ni 'setup.AdvEscalationMod' setup.EscalationMod `{ name: "Advanced escalation module", desc: {Effect : 'Adds a 20% chance of dealing an extra attack'}, price: 180 , qual: 'adv', modif: {allin : 20 }}`>> <<ni 'setup.RareEscalationMod' setup.EscalationMod `{ name: "Rare escalation module", desc: {Effect : 'Adds a 25% chance of dealing an extra attack'}, price: 250 , qual: 'rare', modif: {allin : 25 }}`>> /* Kinetic chargers -------------------------------------------------*/ <<set setup.KinCharger = { name: "Kinetic charger", desc: {Effect : "Spending AP restores <b class='sh'>1</b> shield point"}, texture: setup.locLoad('kincharger'), type: "passive", price: 100 , qual: 'common', modif : {kincharge : 1 }}>> <<ni 'setup.AdvKinCharger' setup.KinCharger `{ name: "Advanced kinetic charger", desc: {Effect : "Spending AP restores <b class='sh'>2</b> shield points"}, price: 150 , qual: 'adv', modif : {kincharge : 2 }}`>> <<ni 'setup.RareKinCharger' setup.KinCharger `{ name: "Rare kinetic charger", desc: {Effect : "Spending AP restores <b class='sh'>3</b> shield points"}, price: 225 , qual: 'rare', modif : {kincharge : 3 }}`>> /* Weapon interface--------------------------------------------------*/ <<set setup.WepInterface = { name: "Weapon interface", desc: {Effect : "Increases weapon damage by 10%"}, texture: setup.locLoad('weapinterface'), type: "passive" , price: 120 , qual: 'common', modif: {weaponsmodifier : 10} }>> <<ni 'setup.AdvWepInterface' setup.WepInterface `{ name: "Advanced weapon interface", desc: {Effect : "Increases weapon damage by 20%"}, price: 200 , qual: 'adv', modif: {weaponsmodifier : 20} }`>> <<ni 'setup.RareWepInterface' setup.WepInterface `{ name: "Rare weapon interface", desc: {Effect : "Increases weapon damage by 25%"}, price: 250 , qual: 'rare', modif: {weaponsmodifier : 25} }`>> /* Dodge module -----------------------------------------------------*/ <<set setup.DodgeModule = { name: "Dodge module", desc: {Effect : "Grants <div class='block'>1</div> block at the start of each turn"}, texture: setup.locLoad('dodgemod'), type: "passive" , price: 250 , qual: 'rare', modif : {blockGain : 1} }>> /* ----------------------- Ammo synthesizer ------------------------ */ <<set setup.AmmoSynt = { name: "Ammo synthesizer", desc: { Effect : "Grants a 10% chance of regaining charges for limited use items at the start of each turn." }, texture: setup.locLoad('ammosynt'), type: "passive" , price: 120 , qual: 'common', modif: {ammosynt : 10} }>> <<ni 'setup.AdvAmmoSynt' setup.AmmoSynt `{ name: "Advanced ammo synthesizer", desc: { Effect : "Grants a 20% chance of regaining charges for limited use items at the start of each turn." }, price: 180 , qual: 'adv', modif: {ammosynt : 20} }`>> <<ni 'setup.RareAmmoSynt' setup.AmmoSynt `{ name: "Rare ammo synthesizer", desc: { Effect : "Grants a 25% chance of regaining charges for limited use items at the start of each turn." }, price: 250 , qual: 'rare', modif: {ammosynt : 25} }`>> /* ------------------------- Crit scanner -------------------------- */ <<set setup.CritScanner = { name: "Stud finder", desc: { flavor : "<p>Know your enemy they say...</p>" , Effect : "Increases critical chance by 5%." }, texture: setup.locLoad('studfinder'), type: "passive" , price: 100 , qual: 'common', modif: {CritChance : 5} }>> <<ni 'setup.AdvCritScanner' setup.CritScanner `{ name: "Advanced stud finder", desc: { Effect : "Increases critical chance by 10%.<br>Increases critical damage by 5%." }, price: 150 , qual: 'adv', modif: {CritChance : 10, CritMultiplier : 5} }`>> <<ni 'setup.RareCritScanner' setup.CritScanner `{ name: "Rare stud finder", desc: { Effect : "Increases critical chance by 15%.<br>Increases critical damage by 10%." }, price: 250 , qual: 'rare', modif: {CritChance : 15, CritMultiplier : 10} }`>>
<<if $enhealth lt (15*$difficulty) and _talk is 1>> <<set _talk -->> <<set _talked to true>> <</if>> <<if $enhealth lt (30*$difficulty) and _disarmed is true and _talk is 1>> <<set _talk -->> <<set _talked to true>> <</if>> <<if _talked is true>> <em>Wait!<br> We can figure something out!<br> Leave it here and I'll stay out of your business, I promise. I do what I gotta do to feed my people. That's all.<br> We can both go our separate ways.</em> <br> <br> <div class="EvenSpace"> <<link "Yeah, we're good.">> <<set $spareriflethug to true>> <<set $vic ++>> <<goto `passage()`>> <</link>> <<link "Nah, I'm killing you for sure.">> <<EnemyTurn>> <</link>> </div> <<elseif _disarmed is true and _range gt 1>> The thug unsheathes a knife and advances toward you. <<set _range ++>> <<elseif _range is 3>> The man shoots you from afar, dealing <<DMG 17>> damage. <<elseif _range is 2 and _enemyuse is 1>> <<set _enemyuse -->> The thug throws a hand-made grenade which deals <<DMG 1 25>> damage. <<elseif _range is 2>> The thug shoots you, dealing <<DMG 1 17>> damage. <<elseif _disarmed is true>> The man pulls out a knife and stabs you for <<DMG 1 8>> damage. <<else>> either("Your opponent takes a quick step back.","Your opponent hits you for <<DMG 1 4>>, pushing you back.") <<set _range ++>> <</if>>
<<NewCombatConfig>> <<CombatUI>> <<DroneMenu>> <<EnemyUI>> <<include 'SplashScreen'>> /* Init system, needs some work <<if $init < $enemy.init>> <<timed 1s>> <<EnemyTurn>> <</timed>> <</if>>*/ /* For looks only */ <div class='fightWrapper'/> <div id="fight"> <p style='margin-top: 12em'> <<if typeof $enemy.desc === 'object'>> /* Is array */ <<= $enemy.desc.random()>> <<else>> /* Single string */ <<= $enemy.desc>> <</if>> </p> </div> /* Warning messages, mostly */ <div id="next">$turn</div> <div id="enhealth"></div>
A young woman with face tattoos. - Dialog options... - <<a 'Fight her!' id 1 goto 'Combat'>> <<fight setup.Efi>> <</a>>
<<widget "bounty">> <<if !tags().includes('combat') and ($hitlist.length + $topay.length + $deathlist.length) gt 0>> <div id="hit" class="side"> - Bounty board - <br> <<for _i to 0; _i < $deathlist.length; _i++>> <div class="grey"> <<= $deathlist[_i]>> </div> <</for>> <<for _i to 0; _i < $topay.length; _i++>> <div class="mon"> <<= $topay[_i]>> </div> <</for>> <<for _i to 0; _i < $hitlist.length; _i++>> <<link $hitlist[_i] `$hitlist[_i] + 'bounty'`>><</link>> <br> <</for>> </div> <</if>> <</widget>>
/*<<run setup.editRoom({content: 'RifleBotTriggered'})>>*/ <p> A flash of light, then the whizz of a bullet grazing you. <br> You make out the slender silhouette of a robot carrying a rifle. Its bears the red shoulder pads of security bots. </p> <b class='red'> "This zone is off-limit." </b> <<if !$hasFought.includes('RifleBot')>> <span> <<a 'Yield.' key 'y'>> <<rep>> <<set _dmg = random(12, 18)>><<health `-1*_dmg`>> <p class='charspeech'> "Sorry, didn't know." </p> <p> The robot moves closer into sight. </p> <b class='red'>"Offenders will be shot on sight."</b> <p> The rifle rises, a flash lights the room and the bullet deals <b class='red'>_dmg</b> damage before you can react. </p> <</a>> </span> <</if>> <<a 'Fight it!' key 'n' goto 'Combat'>> <<fight setup.RifleBot 'rand'>> <</a>>
<p> A sentry stands perfectly still at the center of the room. </p> <<a "Fight it!" id 1 goto 'Combat'>> <<fight setup.SentryBot>> <</a>>
<p> You make out the silhouette of a large cyberbug feasting on some piece of rotten meat. The steady noise of metal mandibules cover your steps. </p> <p> As you get closer, it suddenly turns to face you and hisses aggresively. </p> <<a 'Fight it!' id 1 goto 'Combat'>> <<fight setup.AlphaBug 'rand'>> <</a>>
<<if $cheat && !navigator.userAgent.toLowerCase().match(/mobile/i)>> <<include 'cheatmenu'>> <</if>>
A behemoth of a robot stands ahead. <br><br> <<a "Fight it!">> <<fight setup.BrawlBot>> <<goto 'Combat'>> <</a>>
<p> A highly trained and enhanced assassin. </p> <<a 'Fight her!' id 1 goto 'Combat'>> <<fight setup.HeadHunter>> <</a>>
/*Start at lvl 1*/ <<set $lvl = 1>> /* Pools */ /*<<set setup.enemyPool = { 1 : [ 'RabidDog', 'RabidDogAmbush', 'RabidDog', 'RabidDogAmbush', 'MinorMillipede', 'MinorMillipede', 'CyberBug', 'CyberBug', 'CyberBug', 'CyberBug', 'Automaton','Automaton','Automaton', 'AlphaBug', 'AlphaBug', 'RifleBot' ], 2 : [ 'RabidDog', 'MinorMillipede', 'CyberBug', 'CyberBug', 'Automaton', 'AlphaBug', 'AlphaBug', 'AlphaBug', 'RifleBot', 'RifleBot', 'RifleBot', 'MomBug', 'MomBug' ] }; setup.elitePool = { 1 : [ 'MomBug', 'MomBug', 'RifleBot', 'RifleBot', 'AutomatonDuo' ], 2 : [ 'Sentry', 'MarksBot', 'Overseer', 'BrawlBot', 'Sentry', 'MarksBot' ], 3 : [ 'Sentry', 'MarksBot', 'Overseer', 'Cleaner', 'Assassin', 'MarksBot' ] }>>*/ /*<<set _curioPool = [ 'MaintenanceBot', 'MaintenanceBot', 'MaintenanceBot', 'AugmentCrate', 'AugmentCrate', 'AugmentCrate', 'WeaponCrate', 'WeaponCrate', either('BodySearch', 'BodyLootWep', 'BodyLootMoney'), 'MedKit', 'MedKit', 'MedKitInfected', either('AutomatonAugment','AutomatonScraps'), 'CyberBugSurprised', 'CyberBugSurprised', 'TrapCrate', 'TrapCrate', 'Trigaea', 'CyberbugBody', either('Efi','EfisCorpse'), 'HighLedge', 'LockedRoomEntrance', 'DemoSupplies', 'DemoSupplies', 'SentryZone' ]>>*/ <<set _unique = Story.lookup('tags', 'unique').map(p => p.title), _curios = Story.lookup('tags', 'curio').map(p => p.title), _enemies = Story.lookup('tags', 'enRoom').map(p => p.title), _terrain = Story.lookup('tags', 'terrain').map(p => p.title)>> <<set _time = new Date().getTime()>> /* Coordinates parameters */ <<run $rooms = [{type: 'Start', desc: $netAccess.travel ? 'netStart' : 'startingRoom' }], $visited = [], $roomSeen = [], $MaxX = 12, $MaxY = 12; const roomMax = $MaxY*$MaxX; let i, roomsNum; /* ----------------------------- Boss ---------------------------- */ $rooms.push({type: 'Boss', content: 'Millipede'}); /* --------------------------- Obstacles -------------------------- */ roomsNum = roomMax*(1/5); for (i = 0; i lt roomsNum; i++) {$rooms.push('Obstacle')}; /* --------------------------- Unique -------------------------- */ $rooms.push({type: 'Curio', content : _unique.pluck()}); /* --------------------------- Enemies -------------------------- */ roomsNum = roomMax*(1/7); for (i = 0;i lt roomsNum;i++) { $rooms.push({type: 'Enemy', content: _enemies.random()}); }; /* --------------------------- Elites -------------------------- */ roomsNum = roomMax*(1/50); for (i = 0; i lt roomsNum; i++) { $rooms.push({type: 'Elite', content: ['AlphaBug','MomBug'].random() }) }; /* ---------------------------- Curios ---------------------------- */ roomsNum = roomMax*(1/4); for (i = 0; i lt roomsNum; i++) { $rooms.push({type: 'Curio', content: _curios.random()}) }; /* ------------------------- Spec obstacles ------------------------ */ roomsNum = roomMax*(1/10); for (i = 0; i lt roomsNum; i++) { $rooms.push({type: 'Terrain', content: _terrain.random()}) }; /* ---------------------------- Shop ---------------------------- */ $rooms.push({type: 'Shop', desc: '', content: 'MekasShop'} ); /* --------------------------- Fill rest -------------------------- */ for (i = $rooms.length; i lt roomMax; i++) { $rooms.push({type: 'Empty room'}) }>> <<set _gens = 0>>
The wriggling creature shakes in unsettling motions. The telltale glimmer of nanorobots wraps in and around the exoskeleton like a living oil. Severed tentacles curl frantically around the scene. <<act "Finish it.">>You approach the ominous cadaver, under the ruptured shell shines an activation core. You thrust you arm into the body and pull it out. The dim amber light fades. [[Leave.|Cleaner encounter]] <</act>>
<<widget 'triggerEffect'>> <<if typeof $enemy[_args[0]] === 'string'>> /*Single string*/ <<run $('#fight').wiki($enemy[_args[0]])>> <<elseif typeof $enemy[_args[0]] === 'object'>> /*Is an array*/ <<for _effect range $enemy[_args[0]]>> <<run $('#fight').wiki(_effect)>> <</for>> <</if>> <</widget>>
<<widget "shm">> <center><img src="https://cdn.discordapp.com/attachments/949715863479672913/962393804369973278/shopmanndivid.png"/></center> <span class="shm">"_args[0]"</span> <</widget>>
<p> Carcasses of animals and machines alike litter the floor, yet the room looks perfectly empty. </p> <span> <<adel "Inspect the corpses." id 1>> <<rep>> The corpses are riddled with bullet holes the impacts of which can be seen on the walls. <</adel>> </span> <span> <<adel "Step forward." id 2>> <<set $rooms[$pos].type = 'Enemy'>> <<rep>> As you step in the circle of battered corpses a turret unfolds from the ceiling. <<a "Fight it!" id 1 goto 'Combat'>> <<fight setup.SentryBot>> <</a>> <</adel>> </span>
<<if _range is 3>> The shopkeeper rushes toward you. <<set _range -->> <<elseif _range is 2>> Gregor spits a corrosive substance at you, dealing <<DMG 1 3 'acid'>>. <<set _acid += 4>> <<elseif $enhealth lt 20>> Gregor falls back behind the cover of the counter. <<set _range ++>> <<elseif _range is 1>> <<= either("The talking insect bites you, dealing <<DMG 1 9>>.","The talking insect rends you with its claws, dealing <<DMG 2 5>>.")>> <</if>>
<h2>Informations</h2> <p> Right clicking on items will bring up detailed informations. </p> <<set _rareItem = { name: "Rare item", dir : '_rareItem', desc: "<<once 'passage' 'a'>><<set $count ++>><</once>>"+ "Rare items are more powerful (and expensive)."+ "<<if $count gte 5>><<a 'Proceed' trigger 'displayAgain'>><<run Dialog.close()>><</a>><</if>>", texture: "", icon: "", qual: 'rare'}, _advItem = { name: "Advanced item", dir: '_advItem', desc: "<<once 'passage' 'b'>><<set $count ++>><</once>>"+ "Advanced items are a great value proposition."+ "<<if $count gte 5>><<a 'Proceed' trigger 'displayAgain'>><<run Dialog.close()>><</a>><</if>>", texture: "", icon: "", qual: 'adv'}, _commonItem = { name: "Common item", dir : '_commonItem', desc: "<<once 'passage' 'c'>><<set $count ++>><</once>>"+ "Common items, they are common."+ "<<if $count gte 5>><<a 'Proceed' trigger 'displayAgain'>><<run Dialog.close()>><</a>><</if>>", texture: "", icon: "", qual: 'common'}, _specItem = { name: "Special item", dir : '_specItem', desc: "<<once 'passage' 'd'>><<set $count ++>><</once>>"+ "Some items are special.<br>They often can't be sold..."+ "<<if $count gte 5>><<a 'Proceed' trigger 'displayAgain'>><<run Dialog.close()>><</a>><</if>>", texture: "", icon: "", qual: 'spec'}>> <div class='center'> <<hex _commonItem>><</hex>> <<hex _advItem>><</hex>> <<hex _rareItem>><</hex>> <<hex _specItem>><</hex>> </div> <<done>> <<trigger 'leftclickdesc'>> <</done>>
<<if $victory>> You've beaten the cleaner, which is very impressive and deserves an achievement of its own... <<else>> You make your way back through the oily subterranean intestines. The atmosphere is suffocating and your wounds make every movement difficult. You make out a massive silhouette standing at the end of the tunnel. Who would venture to such a place? <<act "Call out." "choice">>Your voice echoes in the narrow tunnel. The silhouette does not answer but advances in your direction. <<link 'Fight it.' 'Combat'>> <<fight setup.Cleaner>> <</link>> <</act>> <<act "Hide" "choice">>The robot passes in front of you, you notice stuff. Soon, it has disappeared. <</if>>
<br> A slender marksman of a robot. <br><br> <<a "Fight it!">> <<fight setup.MarksBot>> <<goto 'Combat'>> <</a>>
<<widget "act" container>> <<set _id ++>> <span @id="_id"> <<if $args[1] is "choice">> <<link _args[0]>> /* Clears all other numbered IDs (other 'act') */ <<for _i to 1; _i lte _id ; _i++>> <<replace `"#" + _i`>><</replace>> <</for>> /* Replaces first ID with contents */ <<replace "#1">> <center> <img src="https://cdn.discordapp.com/attachments/949715863479672913/959146626423849030/dividerap.png"/> </center> _contents <</replace>> <</link>> <<else>> /* Only replaces captured ID with contents */ <<capture _id>> <<link _args[0]>> <<replace `"#" + _id`>> <center> <img src="https://cdn.discordapp.com/attachments/949715863479672913/959146626423849030/dividerap.png"/> </center> _args[0] _contents <</replace>> <</link>> <</capture>> <</if>> </span> <</widget>>
<p> A stray dog jumps to your throat from the cover of darkness. </p> <<a 'Fight back!' id 1 goto 'Combat'>> <<fight setup.RabidDog>> <</a>>
<<widget "smartbutton">> <<if !_args[1] || (_args[1] && State.getVar('$'+_args[1]))>> <<if _args[0].split(',').includes(passage())>> <<but '' data-content 'Back' key settings.back goto $prev>><</but>> <<else>> <<but '' data-content `_args[0].split(',')[0]` goto _args[0].split(',')[0]>><</but>> <</if>> <</if>> <</widget>>
<<divider 'drone'>> <p> <<= _currentDrone.name>>: <br> <<if !_currentDrone.on>> This drone is inactive. <<elseif _range === 1>> The drone fires and <<EnDMG 3 4 _droneDMG>>. <<elseif _range === 2>> The drone fires and <<EnDMG 2 4 _droneDMG>>. <<elseif _range === 3>> The drone fires and <<EnDMG 1 4 _droneDMG>>. <<else>> The enemy is too far. <</if>> </p>
<<widget "unequip">> <<if _args[0].modif>> /* An object: {noSigilVariable : value}*/ <<run for (const key in _args[0].modif) { if (typeof _args[0].modif[key] === 'string'){ /* Is ammo*/ State.variables[key] = "None"; } else if (typeof _args[0].modif[key] === 'boolean'){ State.variables[key] = !_args[0].modif[key]; } else { State.variables[key] -= _args[0].modif[key]; } }>> <</if>> <<if _args[0].size gt 1>> <<if _args[0].type?.includes('weapon')>> <<set $weaponcapacity += _args[0].size-1>> <<elseif _args[0].type?.includes('drone')>> <<set $dronecapacity += _args[0].size-1>> <<else>> <<set $capacity += _args[0].size-1>> <</if>> <</if>> <</widget>> /*-------------------------------------------------------------------*/ <<widget "equip">> <<if _args[0].modif>> /* An object: {noSigilVariable : value}*/ <<run for (const key in _args[0].modif) { if (typeof _args[0].modif[key] === 'string'){ /* Is ammo*/ State.variables[key] = _args[0].modif[key]; } else if (typeof _args[0].modif[key] === 'boolean'){ State.variables[key] = !_args[0].modif[key]; } else { State.variables[key] += _args[0].modif[key]; } }>> <</if>> <<if _args[0].size gt 1>> <<if _args[0].type?.includes('weapon')>> <<set $weaponcapacity -= _args[0].size-1>> <<elseif _args[0].type?.includes('drone')>> <<set $dronecapacity -= _args[0].size-1>> <<else>> <<set $capacity -= _args[0].size-1>> <</if>> <</if>> <</widget>>
<<widget "ammo">> <<if _totDMG>> /* Makes sure the shot hit... */ <<switch $ammotype>> <<case "Explosive">> <<set _noverb = true>> + <<EnDMG 1 `_num*2` $blastmodifier 'dot'>>. /* 'dot' makes it non-dodgeable */ <<set _noverb = false>> <<case "Shock">> <<for _n = 0; _n lt _num; _n++>> <<= randomFloat(1,10) gt 9? '<<stun>>' : ''>> <</for>> <<case "Acid">> <p class='small'> The round<<= _num gt 1? 's':''>> appl<<= _num gt 1? 'y':'ies'>> <b class='acid'>acid</b> burns. </p> <<set $enemy.DoT.acid += _num>> <</switch>> <</if>> <</widget>>
Shopmann dialog. S - New here? P - Yeah S - Looks like it. P - What about it? -> You'll get used to it I'm sure / Place is fucking dangerous. <<set $dialog = [ ['Prompt 1','Prompt 2'], ['Answer 1','Answer 2'], ]>>
<<widget "breakitem">> <<set _break to _equip.random()>> <<for _item range $equip>> <<if _item.skill === _break>> <<set $storage.push($equip.delete(_item)), _equip.delete(_item)>> <<unequip _item>> <</if>> <</for>> <<set _totskills.delete(_break)>> <b class='red'><<= _break.replaceAll('_', ' ')>></b> <</widget>>
<<if passage() === 'Game'>> <<on 'mapRefresh' 'div' id 'arrowBox'>> <span style='grid-column:span 3'> <<if _move && $rooms[$pos].connect.includes('connectUp')>> <<a "⇑" key settings.keys.up class 'arrow'>> <<run $pos = setup.traverseCorridor($pos, -$MaxX); $(document).trigger('mapRefresh');>> <</a>> <</if>> </span> <span> <<if _move && $rooms[$pos].connect.includes('connectLeft')>> <<a "⇐" key settings.keys.left class 'arrow'>> <<run $pos = setup.traverseCorridor($pos, -1); $(document).trigger('mapRefresh');>> <</a>> <</if>> </span> <span> <<if _move && $rooms[$pos].connect.includes('connectDown')>> <<a "⇓" key settings.keys.down class 'arrow'>> <<run $pos = setup.traverseCorridor($pos, $MaxX); $(document).trigger('mapRefresh');>> <</a>> <</if>> </span> <span> <<if _move && $rooms[$pos].connect.includes('connectRight')>> <<a "⇒" key settings.keys.right class 'arrow'>> <<run $pos = setup.traverseCorridor($pos, 1); $(document).trigger('mapRefresh');>> <</a>> <</if>> </span> <</on>> <</if>>
<<lights 0>> <<if visited(passage()) gt 1>> <div id='game' class='shop' data-title="Gregor's shop"> <span style='padding:1.5em'> A cyberbug with a human face scuttles from behind a decrepit counter. "How can I help you." Gregor shop, managed by a cyberbug with a human face. Low rarity but cheap items... <<if $scraps>> <<linkreplace "<h3>SCRAPS FOR MONEY</h3>">> The trade earns you <b style='color:var(--mon);'>$scraps ₦</b>! <<set $money += $scraps, $scraps = 0>> <<trigger 'UIupdate'>> <</linkreplace>> <</if>> </span> <span> <h3>Buy items</h3> <<ShopGrid 'GregorPool' 'buy'>> <h3>Sell items</h3> <<ShopGrid 'storage' 'sell'>> </span> </div> <<else>> The heavy door opens on a <</if>> <<a 'Back' goto 'Game'>><</a>>
<p>The room ahead is filled with a stench of blood and decay.</p> <p> A corpse lies face down in a dark puddle of murky blood. The man's tattered clothes have been torn to shreds in places, revealing deep wounds in the rotting flesh. </p> <<adel "Search the body." id 1>> <<set _loot = either(setup.PipePistol,setup.ScrapRifle,setup.Sword)>> <<set setup.editRoom( {type: 'Loot', content: 'A _loot.name rests on the ground next to the body.', item : _loot} )>> <<app '#content'>> <p> The man's stiff fingers hold a crude weapon. </p> <<itemloot _loot>> <</adel>>
<p> One of the walls appears weaker than the others, cracks run up and down its weathered surface. </p> <<if $player.inventory.find(item => item.name === 'Demolition charge')>> <<a 'Blow it up.' id 2>> <<set $player.inventory.delete(setup.DemoCharge)>> <<app '#content'>> <p> You place the demolition charge and take a step back before triggering it. <</a>> <</if>>
<p> A strange box lies toppled over in a dark corner of the room. Its shape and design feel entirely foreign to this place and time. </p> <<adel "Open it." key 'y,49'>> <<set setup.editRoom( {type: 'Loot', content: 'The uncanny weapon gleams in the open box.', item : setup.Gunblade} )>> <<app>> <p>The lid slides open to reveal a simple straw hat, and under it a most curious weapon. The long pistol ends in a sharp under-barrel blade.</p> <p>The item feels otherworldly.</p> <<itemloot setup.Gunblade>> <</adel>>
<<if $ShopmannPool.length gt 0 and $shopcapacity is true>> - BUY ITEMS - <div class="grid"> <br> <<for _item range $ShopmannPool>> <<itembuy _item>><br> <</for>> </div> <<if $shopcapacity is true>> <div class="center"> <<itembuy setup.ExtraCapacity>> </div> <</if>> <<else>> As you go toward the usual backroom, William Shopmann coughs. <<shm "I fear, my friend, that my stocks are empty for the moment. Of course I will gladly notify you as soon as new merchandise arrives.">> <</if>> [[Leave.|Consumable items]]
Your steps lead you to a towering storefront, standing at the fork of two spatious streets. The wide golden sign reads "Imperial Emporium". <<link "Go in." "ShopMainFirst">> <<set $selection1.delete('ImperialEmporium')>> <</link>> <<keepgoing>>
Tall, baroque glass doors open on a much smaller boutique, crowded with objects of all kinds. The selection seems organized by size rather than by any other observable quality. A tall man wearing a top hat is sitting at the counter, the blue glow of a screen reflects off his rounded glasses. The slender figure turns to you, a wide grin stretching across his face. <<shm "Welcome to my humble abode traveler. I am William Shopmann, the one and only!">>, he gestures profusely, spreading his arms and inviting you to behold said abode. <<shm "What seekest thee?">> <<act '"Implants Seller, I am going into battle and I want your strongest implants."'>>"Implants Seller, I am going into battle and I want your strongest implants." <<shm "You can't handle my strongest implants traveler. They're too strong for you.">> he whispers maniacally. You feel insulted that this scarecrow of a merchant would question your strengths. <<act '"Implants seller, enough of these games!"'>>"Implants seller, enough of these games!" William Shopmann sighs, his outstretched arms fall to his sides as if struck by sudden tiredness. The rim of the top hat hides his gaze. <<shm "Ah.. as you wish, traveler. This way.">> [[Follow him.|ShopBuyIntro]] <</act>> <</act>>
An imposing white building appears at the corner of a busy street. The extreme cleanliness of the facade clashes with its surroundings. <<act "Get closer.">>Security gards stand on either side of the main entrance, a large sign reads Omni-Clinic. <<link "Go in." "OmniClinic">> <<set $selection1.delete("OmniClinicFront")>> <</link>> <</act>> <<keepgoing>>
0-24 hours <<set setup.time to ["night","late night","early morning","morning","early afternoon","afternoon","evening","late evening"]>> Surface hub <<switch $time>> <<case "night" "late night">> The surface hub is almost empty as this late hour of the night, the air feels cools and still. The dim redness of the artificial lighting clashes with the clear starlit sky. Shadows fill every corner and every street. <<case "early morning" "morning">> The domed surface hub is teaming with activity at this early hour of the day. People and animals roam the vast space, each going about their own business. The purple morning sky looks surreal up above, beyond the glass ceiling. Covered streets and alleyways stretch in every direction like the tunnels of a gigantic ant-hill. <<case "early afternoon" "afternoon">> The torrid sun bears down on the darkened glass ceiling, few are willing to brave the suffocating afternoon heat. The surface hub fills like a giant cloth tent strung in the middle of a desert, there is something homely to the ocher shadowed city. <<case "evening" "late evening">> Shades of purple fill the sky above as the sun sets, out of sight. <</switch>> Surface <<switch $time>> <<case "night" "late night">> Stars fill the night sky above the covered street. <<case "early morning" "morning">> The morning rays cast a peach light on the clouds hanging high above the city. <<case "early afternoon" "afternoon">> Bright rays of light rains down from the dome ceiling, the torrid sun bears down on the covered city despite the air conditionning. <<case "evening" "late evening">> Shades of purple fill the sky above as the sun sets, out of sight. <</switch>> Depth levels <<switch $time>> <<case "late evening" "night" "late night">> The dim red lighting fills the street with indistinct shadows. <<case "early morning" "morning">> White lights on the ceiling cast sharp vertical shadows on the street. <<case "early afternoon" "afternoon">> Golden artificial light bathes the street. <<case "evening">> The orange <</switch>>
Difficult/dangerous terrain
Welcome to Hidden Eden! Grows and sells a vast array of hallucinatory drugs, has a good number of jobs for you. Adam, Bob Marley vibes, former leader of an organicist movement, had to flee to the 2nd depth. His views have mellowed with time.
<<widget "statchange">> <<if State.getVar('_'+_args[0]) !== State.getVar('$'+_args[0])>> <p>_args[1] : <b class=red><<= '$'+_args[0]>></b></p> /* set tempclone to new value */ <<= "<<set _"+_args[0]+" = $"+_args[0]+">>" >> <<else>> <p>_args[1] : <<= '$'+_args[0]>></p> <</if>> <</widget>>
<<script>> /* Maliface's inputbox macro! Syntax: <<inputbox type 'variable' attribute value...>> ...code that runs when 'enter' is pressed... <<onchange>> ...code that runs whenever the input value is modified... <</inputbox>> */ Macro.add('inputbox', { tags: ['onchange'], isAsync : true, handler() { const onchange = this.payload.find(pay => pay.name === 'onchange'), onenter = this.payload[0].contents; let type = this.args[0], varName = this.args[1], varType, attributes = this.args.slice(2); // Broad error checks if (this.args.length < 2) { return this.error(`Missing input type or associated variable`); } if (typeof type !== 'string') { return this.error(`Input type is not a string, reading: "${type}"`); } if (typeof varName !== 'string' && !Array.isArray(varName)) { //Not a string nor array return this.error(`Invalid variable name, reading: "${varName}"`); } // Setting varType if (varName[0] === '$' || varName[0] === '_') { varType = 'state'; } else if (varName.split('.')[0] === 'setup') { varType = 'setup'; } else if (varName.split('.')[0] === 'settings') { varType = 'settings'; } else { return this.error(`Unrecognized variable type: "${varName}"`); } // Create input with type const input = jQuery(document.createElement('input')); // Applies attribute for (let i = 0; i < attributes.length;i+=2) { if (typeof attributes[i] === 'object'){ //JQuery style object input.attr(attributes[i]); i--; } else { // Simple pairs input.attr(attributes[i], attributes[i+1]); } } input.attr({ type : type, id : input.attr('id') === undefined ? `inputbox-${type}-${Util.slugify(varName)}` : input.attr('id'), name : input.attr('name') ? input.attr('name') : `${type}input-${Util.slugify(varName)}`, tabindex : 0}) .addClass(`macro-inputbox`); // Check for label property, if found, if (input.attr('label')){ var label = jQuery(document.createElement('label')) .attr('for', input.attr('id')) .text(input.attr('label')); input.removeAttr('label'); } function enforceType(inputValue) { const value = isNaN(Number(inputValue))||type === 'text'? inputValue : Number(inputValue); return value; } $(input).on('input.macros', this.createShadowWrapper( function() { State.setVar(varName, enforceType(this.value)); if (varType === 'settings') { Setting.save(); } if (onchange != null) { $.wiki(onchange.contents); } })) .on('keypress.macros', this.createShadowWrapper( function (ev) { if (ev.which === 13) { // Enter keycode ev.preventDefault(); State.setVar(varName, enforceType(this.value)); if (varType === 'settings') { Setting.save(); } if (onenter != null) { $.wiki(onenter); } if ($(this).attr('goto')){// To passage Engine.play($(this).attr('goto')); } } }) ) label ? label.appendTo(this.output) : '' ; input.appendTo(this.output); } }); <</script>>
<<if _range === 1>> <<skill setup.Katana 'Katana slash'>> <<AP 1 'movefor'>> <<append "#fight">> <br> The wide slash <<EnDMG 1 25 `[$weaponsmodifier, $cqcmodifier]`>>. <br> <</append>> <</skill>> <<else>> <<skill setup.Katana "Dash n' slash">> <<AP 1>> <<range -1>> <<append "#fight">> <br> You dash forward, the slash <<EnDMG 1 20 `[$weaponsmodifier, $cqcmodifier]`>>. <br> <</append>> <</skill>> <</if>>
<div class="info">Rapid reconstruction</div> <<a " <img src='https://cdn.discordapp.com/attachments/949715863479672913/952756505583710248/hiveheal.png' class='skill'> <div class='info'>Rapid reconstruction</div> " id _i+1>> <<if _AP is 0>> <<else>> <<set _last to "buff">> <<AP 1>> <<set _heal = Math.round(12*$healmodifier*randomFloat(0.8,1.2))>> <<set $health += _heal>> <<if $health gt $MaxHealth>><<set $health = $MaxHealth>><</if>> <<set _DMGresist += 0.3>> <<health>> <<append "#fight">> <br> The sleek swarm assembles around your body, healing you for <b style="color:var(--hp);">_heal HP</b> and protecting you from incoming damage. <br> <</append>> <</if>> <</a>>
<<if _turn === 1 && $enemy.AP === 1>> <<divider 'buff'>> <p> The still automaton wakes from its slumber. </p> <<set $enemy.AP ++>> <<elseif $enemy.AP === 4>> <<divider 'buff'>> <p> <<silently>><<EnDMG 1 3000 'dot'>><</silently>> </p> <<elseif _turn !== 1 && _turn%2 && _action === $enemy.AP>> <<divider 'buff'>> <p> The robot grows increasingly frantic. </p> <<set $enemy.AP ++>> <<elseif $enemy.AP gt 2>> /* Fast version */ <<if _range === 1>> <<divider 'enemy'>> <p> The robot flails its long arms around, <<DMG 2 8>>. </p> <<else>> <<divider 'movefor'>> <p> The automaton rushes toward you. </p> <<range -2>> <</if>> <<else>> /* Default version */ <<if _range === 1>> <<divider 'enemy'>> <p> The robot hits you, <<DMG 1 8>>. </p> <<else>> <<divider 'movefor'>> <p> The automaton walks toward you. </p> <<range -1>> <</if>> <</if>>
<<if $enhealth lte 125 and $enhealth gt 100>> <<divider 'enemy'>><br> The most damaged automaton explodes in ball of fire <<if _range ==1>> , dealing <<DMG 1 30>> and pushing you back. <<set _range ++>> <<elseif _range ==2>>, dealing <<DMG 1 10>>. <<else>>.<</if>> <<set $enhealth = 100>> <<elseif $enhealth lte 150>> <<include 'Automatonbehav'>> <<elseif _range gt 1>> <<divider 'movefor'>><br> The pair of robots walks menacingly toward you. <<range -1>> <<elseif _range is 1>> <<divider 'enemy'>><br> The robots lash out, dealing <<DMG 2 10>>. <</if>>
One time lvl 2 encounter: One automaton, first encounter with the Puppeteer. Automatons explode on death, leaving very few identifiable parts. From observing them in combat, they seem machanically simple, could be built from widely available parts scavenged. Seeing an autonomous robot that isn't state-owned feels very strange, especially as it self-desctructs, in a place where any scrap has value (Meka brings up this point when you tell her about the encounter). NPCs say they know nothing about these things, except for Efi who has heard rumors but nothing more. Gregor (if kept alive), knows a lot more, when he was on the market for full body replacement, he was told there was a character of the hilk, operating on Second Depth, a genius who could craft robotic part from anything he found and had a liking for semi-autonomous automatons. "How much credit to give to these rumors?" Gregor believes that given a large enough number of people, some notable characters are bound to emmerge. Beside, someone else crafting autonomous robots would likely threaten the state monopoly on these... Come into the service of the Puppeteer: The production of advanced autonomous robots requires very involved equipment. Security bot parts are easy to salvage, yet they are quite basic in their function, they are "read-only" in a way, the programming cannot be changed or evolve in situation. For that, one needs a constructor core, which can in turn programm any number of simpler brains. The Puppeteer recognizes that his current automatons are quite simple, even compared to public robots, yet creating their "mind" requires extensive efforts. The Puppeteer wants you to steal a constructor core from one of the manufacturing sites. What the Puppeteer doesn't tell you is that he has also noticed emmergent nano-machines behaviours, which he plans to use in conjunction with the constructor core...
The future, climate has gotten very hot, leading to the construction of the Domed Cities, multi-level hives that spread underground. Over the centuries, social and political life has become more and more centered around these cities, splitting Nigeria into the Nigerian Confederation. Each city has its own elected parliament and laws, in federal fashion. The same process has taken place in other parts of equatorial Africa, leading to countries dissolving in favour of trade alliance between cities, leading to what is casually called "the Wider Confederation" (Ghana, Togo, Benin, Cameroon)... These cities have adopted the Nigerian naira as a currency when falling into its sphere of influence. Ibadan is the Confederation's 4th largest city, home to 10.2 million inhabitants. The current period is one of economic growth under a fairly liberal parliament (Park Chung Hee style) that borders on authoritarian. Each city has become its own microcosm with a social hierarchy and traditions. The physical organisation of life in depth levels echoes the social division. It is, however, a fairly equalitarian society, with a numerous middle-class living mainly at surface level, and to whom the economic growth benefits. This social divide between middle-class and the rest is echoed in the access to techonological augmentation. Quite common on surface level, much less below. The right and ability of a city to produce autonomous robots is tightly controlled, and only granted to a few: Ibadan is one of them. It is an industrial monopoly shrouded in mystic, which relies on extensive research. Autonomous forcekeeping is widely employed. Implants and technology: Few main types: Entertainement: For the most priviledged, includes integrated screens, enhanced sensitivity... all matters of pleasant wonders can be acquired for the right price. Robotic and drugs often mix and intertwine. Life improvement and prosthetics: Common improvements such as enhenced eye-sight, modified organs, or two replaced damaged body parts and extend life. Large medical field that fuels the profits of the OmniClinic... Combat technology: those who serve in the military receive incentives for body improvements, they do pay for it but at a much reduced price. Reveiving these implants is the main draw for people to enlist. After the end of their servive, they are supplied with replacement prosthetics fit for civilian life. Still, military-grade implants find their way onto the black market, through theft or corruption. Another type of cruder equipement is that crafted in small local shops... Two types of installs: partial frames and full frames. Nerve signals have to be transformed into mechanical signals to activate an implant, then the other way around to provide feedback. Full frame means that the interface between man and machine happens at the level of the spinal chord. The operation is extensive, costly, and "full frames" almost always have implants for limbs. Partial frames are localized implants, the transition usually happens where the amputation has happened. Cheaper, less invasive, usually comes down to a single limb, or organ. Much of this technology relies on nano-machines for repairs of both biological and mechanical features. They are miniscule, mass-produced robots, that can repair most things with very simple data points. Most manufactured matter bears indentifying token in it's chrystalline structure that nano-bots can evaluate. The cardinal rule is that they cannot produce more of themselves, despite having the theoretical ability of doing so (the fear is obviously that they could consume all the available matter in this circle). Strict rules, protocols and design requirements have been implemented so that this situation is impossible.
<<a "Training dummy" goto "Combat">> <<fight setup.TrDummy>> <</a>> - THUGS - <div class="center"> <<a "Thug" goto "Combat">> <<fight setup.Thug>> <</a>> <<link "RifleThug" "Combat">> <<fight setup.RifleThug>> <</link>> <<link "ThugBrawler" "Combat">> <<fight setup.ThugBrawler>> <</link>> <<a "Efi" goto "Combat">> <<fight setup.Efi>> <</a>> </div> - ISOBOT - <<a 'Isobot' goto "Combat">> <<fight setup.Isobot>> <</a>> - CYBERBUGS - <div class="center"> <<link "CyberBug" "Combat">> <<fight setup.CyberBug>> <</link>> <<link "AlphaBug" "Combat">> <<fight setup.AlphaBug>> <</link>> <<link "Gregor" "Combat">> <<fight setup.Gregor>> <</link>> <<link "Cyber bugs swarm" "Combat">> <<fight setup.CBSwarm>> <</link>> <<link "Mom bug" "Combat">> <<fight setup.MomBug>> <</link>> </div> - AUTOMATONS - <div class="center"> <<link "Automaton" "Combat">> <<fight setup.Auto>> <</link>> <<link "Automatons x 2" "Combat">> <<fight setup.Auto 2>> <</link>> <<link "AutomatonDuo" "Combat">> <<fight setup.AutoDuo>> <</link>> </div> <<a "Millipede" goto "Combat">> <<fight setup.Millipede>> <</a>> <<a 'Minor millipede' goto 'Combat'>> <<fight setup.MinorMillipede>> <</a>> <<link "RabidDog" "Combat">> <<fight setup.RabidDog>> <</link>> <<link "SentryBot" "Combat">> <<fight setup.SentryBot>> <</link>> <br> <<link "RifleBot" "Combat">> <<fight setup.RifleBot>> <</link>> <br> <<link "BrawlBot" "Combat">> <<fight setup.BrawlBot>> <</link>> <br> <<link "Cleaner" "Combat">> <<fight setup.Cleaner>> <</link>> <br> <<link "RiotBot" "Combat">> <<fight setup.RiotBot>> <</link>> <br> <<link "Head hunter" "Combat">> <<fight setup.HeadHunter>> <</link>> <br> <<link "MarksBot" "Combat">> <<fight setup.MarksBot>> <</link>> <br> <<link "Boss" "Combat">> <<fight setup.Boss>> <</link>> <<link "RunawayAI" "Combat">> <<fight setup.RunAI>> <</link>> <<a 'Overseer' goto 'Combat'>> <<fight setup.Overseer>> <</a>>
It seems of rule of never producing self-replicating nano-machines has been broken, or at least circumvented. The emergent behaviour does not break this rule. However nano-machines, which are purpose-built and gregarious in nature, can build an alternative model of themselves, which is different enough to not break the rule, but acts as an evolved form of the species. Then, this new species can in turn modify the default nano-machines into altered version. These two types of machine then organize in colonies. This evolutionnary jumps couldn't have been an accident, nano-machines cannot reproduce, so they cannot evolve on their own, there can be no replucation drift along the generations. Leads to think that the alternative type has been manufactured by someone who knew hat they were doing.
<<if _enemyuse>> <<if _range gt 1>> <<divider 'enemy'>> <img src='https://cdn.discordapp.com/attachments/949715863479672913/1032221465451429918/millimissiles.png' class='actionBanner'> <p> Missiles emerge from under the insect's segmented plates.<br>The volley heads straight for you, <<DMG 4 6>>. </p> <<set _enemyuse -->> <<else>> <<divider 'moveback'>> <p> The mechanical insect puts distance between you. </p> <<range 1>> <</if>> <<elseif $health lt $MaxHealth/2>> <<if _range gt 1 && _action === 3>> <<divider 'enemy'>> <p> The insect launches quills from its body, <<DMG 2 3>>. </p> <<elseif _range gt 1>> <<divider 'movefor'>> <p> The insect rushes toward you. </p> <<range -1>> <<elseif !_ground>> <<divider 'enemy'>> <p> The millipede winds itself around your body and bites you, <<DMG 1 6>>. </p> <<set _ground = true>> <<else>> <<divider 'enemy'>> <p> <<= either( 'The millipede bites you, <<DMG 1 10>>.', 'The sharp legs of the insect dig into your flesh, <<DMG 2 6>>.' )>> </p> <</if>> <<else>> <<if _range gt 2>> <<divider 'enemy'>> <p> The insect launches quills from its body, <<DMG 2 3>>. </p> <<elseif _range === 2>> <<divider 'enemy'>> <p> The insect launches quills from its winding body, <<DMG 3 4>>. </p> <<elseif _action === 3>> <<divider 'enemy'>> <p> The millipede bites you, <<DMG 1 8>>. </p> <<else>> <<divider 'moveback'>> <p> The enemy scuttles back. </p> <<range 1>> <</if>> <</if>>
- INVENTORY - <<if $scraps>> <div class='center'> <<useitem setup.Scraps>> </div> <</if>> <<on 'consume' 'div' class `$player.inventory.length gte $gridwidth ? 'grid' : 'center'`>> <<for _item range $player.inventory>> <<useitem _item>><br> <</for>> <</on>> <<a "Back" goto $prev>> <</a>>
<br> A pair of plain automatons advance silently toward you. The unnatural judder of their gait makes you uneasy. <br> <br> <<a 'Fight them!' id 1>> <<fight setup.AutoDuo 'rand'>> <<goto 'Combat'>> <</a>>
<<widget "HP">> <<switch settings.HPdisplay>> <<case 'ASCII'>> /* ASCII bar */ <<done>> <<run let full = '', empty = '', shield = ''; const shieldI = _shield !== undefined ? _shield : $shield; console.log(shieldI); for (let i = 0; _i lt ($MaxHealth/5); _i++){ if (i lt $health/5){ full += 'I'; } else { empty += 'I'; } }; for (let i = 0; _i lt shieldI/5; _i++){ shield += 'I' } $('#asciibar').empty().wiki(` <b class='sh'>${shield}</b> <b class='grey'>${empty}</b> <b class='hp'>${full}</b> `); >> <</done>> <div id='asciibar'></div> <<case 'bar'>> /* bar */ <<set _ratio = ($health/$MaxHealth)*100>> <div class="health-bar"> <<if _shield === 0>> <<elseif _shield lt $shield>> <div class="shield" @style="'--shield-value:'+(_shield/$shield)*100+'%;--shield-dmg'"></div> <<else>> <div class="shield" style='--shield-value:100%'></div> <</if>> <<done>> <<if _ratio lt 5>> <<run $(".health").css('z-index','-3');>> <<elseif _ratio gt 95>> <<run $(".HPbarshadow").css('z-index','-3');>> <</if>> <</done>> <div class='HPbarshadow' @style="'height:'+ (100 - _ratio) +'%;'"> </div> <div class="health" @style="'--health-value:'+ _ratio +'%;'"> </div> </div> <<default>>/* Numbers */ <<set _ratio = (_shield/$shield)*100>> <<set _hpStyles = (_shield && _shield lt $shield ? 'border-top:none; border-radius: 0 0 var(--radius) var(--radius);' : '') + 'height: '+(_shield/$shield)*100+'%'>> <div class='shieldbox'> <b class='hp'>$health</b> <b class='hp'>$MaxHealth</b> <div @class="(_shield || passage() !== 'Combat' ? 'shielded' : '')+(_shield && _shield lt $shield? ' dam':'')" @data-sh='_shield ?? $shield' @style='_hpStyles'/> </div> <</switch>> <</widget>>
<<widget "useitem">> <<hex _args[0] `'Use '+_args[0].name`>> <<if _args[0].type === 'consumable'>> <<run Dialog.setup('','dialog'+_args[0].qual, 'consume'), Dialog.wiki("<<consume _args[0]>>"), Dialog.open()>> <</if>> <</hex>> <</widget>>
<div id="cheatmenu" tabindex="0"> <<button 'Update UI'>> <<trigger 'UIupdate'>> <</button>> - Health - <<input number `['$health','$MaxHealth','$regen','$healmodifier','$shield','$kincharge','$blockGain']` placeholder `['Health','Max health','Regen','Heal modifier','Shield','Kinetic charge','Block gain']`>> - Econ - <<input number `['$money','$scraps']` placeholder `['Money', 'Scraps']`>> - Capacities - <<input number `['$AP','$capacity','$weaponcapacity','$dronecapacity','$maxBlock']` placeholder `['Action points','Upgrade capacity','Weapon capacity','Drone capacity','Maximum block']`>> - Modifiers- <<input number '$DMGresist' placeholder 'Damage resistance'>> <<input number '$extrause' placeholder 'Extra uses'>> <<input number '$stunmodifier' placeholder 'Stun modifier'>> <<input numbr '$weaponsmodifier' placeholder 'Weapon damage'>> <<input number '$rangemodifier' placeholder 'Ranged damage'>> <<input number '$cqcmodifier' placeholder 'CQC damage'>> <<input number '$elecmodifier' placeholder 'Electric damage'>> <<input number '$blastmodifier' placeholder 'Blast damage'>> <<input number '$allin' placeholder 'Extra action odds'>> <<input number '$ammosynt' placeholder 'Ammo regen'>> <<input number '$freemove' placeholder 'Free move'>> - Meta - <<input number '$exp' placeholder 'Experience'>> <<input number '$difficulty' placeholder 'Difficulty'>> - Drones - <<input number "$droneDMG" placeholder 'Drone damage'>> <<input number "$droneaffinity" placeholder 'Drone affinity'>> </div>
<<widget "edit">> <<input number '_id' placeholder _args[0] tabindex -2>> <<but "☑" tabindex -2 class but id butttd>> <<= "<<set $" + _args[0] + "= _id>>">> /* Updates UI (lazy approach)*/ <<trigger 'UIupdate'>> <</but>> <</widget>>
<<switch $time>> <<case "night" "late night">> The surface hub is almost empty as this late hour of the night, the air feels cools and still. The dim redness of the artificial lighting clashes with the clear starlit sky. Shadows fill every corner and every street. <<case "early morning" "morning">> The domed surface hub is teaming with life at this early hour of the day. Covered streets and alleyways stretch in every direction like the branching tunnels of an ant-hill. <<case "early afternoon" "afternoon">> The torrid sun bears down on the darkened glass ceiling, few are willing to brave the suffocating afternoon heat. The surface hub fills like a giant cloth tent strung in the middle of a desert, there is something homely to the ocher shadowed city. <<case "evening" "late evening">> As the heat of the day recedes, the streets fill once again with activity. The clamor of countless voices echoes under the domed surface hub. Groups form and disperse, Up above, the setting sun casts a fiery haze on the pastel sky. <</switch>> <<keepgoing "Roam the streets.">>
<<set $rooms[$pos].type = 'Locked'>> <p>One of the walls bears a heavy door. It looks extremely sturdy, without visible hinges nor any opening mechanism.</p> <<if $player.inventory.find(item => item.name === 'Inner network key')>> <<a 'Access the inner network.' id 1 goto 'InnerNetworkAccess'>><</a>> <</if>> <<if $player.inventory.find(item => item.name === 'Demolition charge')>> <<a 'Blow it up.' id 2 goto 'InnerNetworkAccess'>><</a>> <</if>>
<<lights 0>> <div id='game' class='shop' data-title="Shopmann's"> <span style='padding:1.5em'> William Shopmann is sitting behind the counter, <<= either("wearing his usual tophat.","reading a book which looks miniscule in his long hands.","polishing some baroque trinket with a cloth.","he grins in your direction as you enter the shop.")>> <<if $scraps>> <<linkreplace "<h3>SCRAPS FOR MONEY</h3>">> The trade earns you <b style='color:var(--mon);'>$scraps ₦</b>! <<set $money += $scraps, $scraps = 0>> <<trigger 'UIupdate'>> <</linkreplace>> <</if>> </span> <span> <h3>Buy items</h3> <<ShopGrid 'ShopmannPool' 'buy'>> <h3>Sell items</h3> <<ShopGrid 'storage' 'sell'>> </span> </div> <<a 'Back' goto 'Game'>><</a>>
<div> <div class='buttonRow'> <<if $MekaPool.length>> <<but 'Buy' class 'activeBut' id 'but1'>> <<run setup.toggleShop(1)>> <<rep '#innerShop'>> <h3>Buy items</h3> <<ShopGrid 'MekaPool' 'buy'>> <</but>> <</if>> <<if $equip.length + $weapons.length + $storage.length>> <<but 'Sell' id 'but2'>> <<run setup.toggleShop(2)>> <<rep '#innerShop'>> <h3>Sell items</h3> <<ShopGrid 'sell'>> <</but>> <</if>> <<but 'Services' id 'but3'>> <<run setup.toggleShop(3)>> <<rep '#innerShop'>> <div class='settingBox' data-title='Healing station' style='display:grid'> <<include 'MekaRepair'>> </div> <div class='settingBox' data-title='Scraps for money' style='display:grid'> <img @src="setup.locLoad('scraps')" style='max-height:40vh'> <<if $scraps>> <<linkreplace "Trade them in.">> The trade earns you <b style='color:var(--mon);'>$scraps ₦</b>! <<set $money += $scraps, $scraps = 0>> <<trigger 'UIupdate'>> <</linkreplace>> <<else>> You have no scraps to trade. <</if>> </div> <</but>> </div> <div id='innerShop' class='shop' @style="'min-width:'+$innerShopWidth+'px'"> /* Default is buy */ <h3>Buy items</h3> <<ShopGrid 'MekaPool' 'buy'>> </div> </div> <<done>> <<run $('#content').css('max-width','50vw'); $(document).one('mapRefresh', () => { $('#content').css('max-width','25vw'); }) >> <<run $('#innerShop').css('width', $('#innerShop').width()+'px') .css('height', $('#innerShop').height()+'px') >> <</done>>
<div id='blackScreen'> <div id='initSpin'></div> <span id='spinText' style='position:absolute'>...sizing map...</span> </div> <div id='game'> <<include 'Content'>> <<include 'Map'>> <<include 'arrowbox'>> </div> <<done>> <<run setup.roomShrink(3)>> <</done>>
<<script>> Macro.add(['a','adel','but','butdel'], { isAsync : true, tags : ['rep','prep','app'], handler() { const type = (this.name[0] === 'b') ? 'button' : 'link', attributes = this.args.slice(1), payload = this.payload[0].contents.trim(); const Rep = this.payload.find(pay => pay.name === 'rep'), Prep = this.payload.find(pay => pay.name === 'prep'), App = this.payload.find(pay => pay.name === 'app'); if(this.args[0] === undefined) return this.error(`No ${type} text supplied.`) // Create element let link = $(document.createElement(type === 'button'? type : 'a')); // Turn argument pairs into html property/value pairs for (let i = 0; i < attributes.length;i++) { if (typeof attributes[i] === 'object'){// jQuery style object link.attr(attributes[i]); } else { //Simple pairs link.attr( attributes[i], attributes[i+1]); i++; } } //Built-in event trigger if (link.attr('trigger')){ var trig = link.attr('trigger').split(','); trig = trig.map(event => event.trim()); link.removeAttr('trigger'); } // Goto attribute if (link.attr('goto')){ var passage = link.attr('goto'); link.removeAttr('goto').attr('data-passage', passage); // Default link processing if (Story.has(passage)) { link.addClass('link-internal'); if (Config.addVisitedLinkClass && State.hasPlayed(passage)) { link.addClass('link-visited'); } } else { link.addClass('link-broken'); } } // Key attribute if (link.attr('key')){ let keyArray = link.attr('key').split(','); keyArray = keyArray.map(key => key.trim()); link.removeAttr('key'); // Event handler $(document).on('keyup', function(e) { keyArray.every(key => { if (e[isNaN(Number(key)) ? 'key' : 'keyCode'] == key){ e.preventDefault(); link.click(); return false; //Stops the every() //Makes sure it runs only once even if redundant keys are given } return true; }) }) } /* Save old _this */ const oldThis = State.temporary.this !== undefined ? State.temporary.this : null; //Doesn't take special link syntax so core profile it is link.wikiWithOptions({ profile : 'core' }, this.args[0]) .addClass(`macro-${this.name}`); link.ariaClick({ namespace : '.macros', role : type , one : (this.name.length > 3 || passage !== undefined) ? true : false}, this.createShadowWrapper( (e) => { State.temporary.this = link; /* Add proper shadow value*/ payload ? $.wiki(payload) : null ; Rep ? $(Rep.args[0] ?? link.parent()) .empty().wiki(Rep.contents) : null ; Prep ? $(document.createDocumentFragment()).wiki(Prep.contents).prependTo(Prep.args[0] ?? link.parent()) : null ; App ? $(App.args[0] ?? link.parent()).wiki(App.contents) : null ; trig ? trig.forEach(event => {$(document).trigger(event)}) : null ; }, () => { if (passage != null){ //Go to passage Engine.play(passage) } else if (this.name.length > 3){ //Remove link link.remove() } oldThis !== null? State.temporary.this = oldThis : delete State.temporary.this; /* Shadow cleanup */ })).appendTo(this.output); } }); <</script>>
<p> The wreck of a rescue bot lies scattered in a corner. Its damaged body is covered in a thick film of sticky machine oil. </p> <p> The sealed compartment which holds medical equipment seems unscathed. </p> <<adel 'Search for medical supplies.' id 1>> <<set $rooms[$pos] = {type: 'Loot', content: 'The destroyed rescue bot still holds a few supplies.', item : setup.InfectedMedkit}>> <<app '#content'>> <p>The container is stuck shut and requires vigorous prying to open. You find a Medkit inside.</p> <<itemloot setup.InfectedMedkit>> <</adel>>
The decrepit tunnel leads to a circular room. A low winding shadow crawls toward you with a rising hiss. The mechanical millipede curls up threateningly. Simple segmented machines, even years after the war, they remain fearsome killers... <<a "Fight it." id 1 goto 'Combat'>> <<fight setup.Millipede '' 'Game'>> <</a>>
<<widget 'flee'>> <span id='f'> <<a 'Try to flee!' id 2>> <<set _xx = (random(-1,1)+$x)>> <<set _yy = ($y + random(-1,1))>> <<if $obstacles.includes(_yy+'-'+_xx) || _yy gt $MaxY || _xx gt $MaxY || _yy lt 1 || _xx lt 1 >> <<replace "#f">>Failure<</replace>> <<else>> <<set $y = _yy>> <<set $x = _xx>> <<refresh>> <</if>> <</a>> </span> <</widget>>
/* Creates temp clones of story vars*/ <<for _i range setup.stats>> <<= "<<set _"+_i+" = $"+_i+">>" >> <</for>> Kinetic recharge : recovers 1-5 shield/action. Positive feedback loop : gain 2-10 heat/action. <br> <div style='display: grid;grid-template-columns: 1fr 1fr;' id=lvl> <<include 'leveling'>> </div> <<a 'Done' id 1>> <<for _i range setup.stats>> <<= "<<set $"+_i+" = _"+_i+">>" >> <</for>> <<set $difficulty += .2>> <<set $lvl ++>> <<set $MaxHealth = $health>> <<app>><<include `'setup lvl '+$lvl`>><</append>> <<goto 'Game'>> <</a>>
<<lights 0>> <h2>Welcome!</h2> <p style='font-weight:bold'> This is a proof of concept complete with missing assets, fucked up balance and placeholders, beware! </p> <h3>Controls</h3> <p> Use WASD, ZQSD or the arrow keys to navigate the map. </p> <p> In combat, skills are mapped to their corresponding number key. </p> <p> Right clicking on items (hexagonal container) displays extra informations. </p> <h3>Play</h3> [[Go to game|Game]]
<<on 'mapRefresh' 'div' id 'content'>> /*-------------------------- PassageReady ---------------------------*/ <<silently>> <<set _room = $rooms[$pos]>> <<if !$visited.includes($pos) && $health lt $MaxHealth>> <<set $health += Math.round($health < $MaxHealth/4 ? $regen*1.5 : $regen)>> <<trigger 'UIupdate'>> <</if>> /* Time counter */ <<if $visited.includes($pos)>> <<time `random(1,3)`>> <<elseif _room.type === 'Terrain'>> <<time `random(5,10)`>> <<else>> <<time `random(2,5)`>> <</if>> /* Lights to default */ <<lights 2>> <<set $visited.pushUnique($pos), _id = 0, _move = true, $roomSeen = $roomSeen.concatUnique( _room.possible , $pos)>> <</silently>> /*----------------------------- Content -----------------------------*/ <span class='header'/> /* Description */ <<if _room.desc>> <<if _room.desc.length gt 20>> /* Description is a sentence */ <p><<= _room.desc>></p> <<else>> /* Description is a passage name */ <<include _room.desc>> <</if>> <</if>> /* Content */ <<if _room.content?.length gt 20>> /* Content is a sentence */ <p><<= $rooms[$pos].content>></p> <<elseif _room.content>> /* Content is a passage name */ <<include $rooms[$pos].content>> <</if>> /* Loot */ <<if Array.isArray(_room.item)>> /* Loot is an array of objects */ <div class='gridsmall'> <<for _item range $rooms[$pos].item>> <<itemloot _item>><br> <</for>> </div> <<elseif typeof _room.item === 'object'>> /* Loot is a single object */ <<itemloot _room.item>> <<elseif typeof _room.item === 'string'>> <<= _room.item>> <</if>> /* Move/flee option when enemy... */ <<if ['Enemy','Elite'].includes(_room.type)>> <<set _move = $cheat ? true : false>> /* Stops player from moving */ <<if !$rooms[$pos].fled>> <<adel 'Try to flee' id 'f'>> /* Odds of taking damage */ <<if $AP + $rooms[$pos].possible.length lt random(10)>> <<set _dmg = random(5,15)>> <<health `-_dmg`>> <</if>> /* Odds of escaping */ <<if $rooms[$pos].possible.length gt randomFloat(0,4)>> /* Needs fixing! */ <<set $pos = $rooms[$pos].possible.random()>> <<trigger 'mapRefresh'>> <<run $('.header').wiki(" You manage to flee<<= _dmg ? ' but suffer <b class=red>_dmg</b> damage while escaping' : ''>> ")>> <<else>> <<run $('#content').wiki("You fail <<= _dmg ? ' and suffer <b class=red>_dmg</b> damage' : ''>>. ")>> <<set $rooms[$pos].fled = true>> <</if>> <<unset _dmg>> <</adel>> <</if>> <</if>> /*---------------------- PassageDone equivalent ---------------------*/ <</on>>
<<script>> // <<app/prep>> macros Macro.add(['app', 'prep'], { tags : null, handler() { let target, output; // If number of args is even, throw an error, coming soon, maybe... if (this.args.length && this.args.length % 2 != 1) { return this.error('Number of arguments must either be odd: selector + (attribute + value)... or 0'); } // Sets '.passage' as target if args[0] is falsy target = (this.args[0]) ? $(this.args[0]) : $('.passage'); // Creates span and applies arguments output = $(document.createElement('span')); for (let i = 1; i < this.args.length;i+=2) { output.attr( this.args[i] , this.args[i+1] ); } output.wiki( this.payload[0].contents ); // Prepend or append switch (this.name) { case 'app': target.append(output); break; case 'prep': target.prepend(output); break; } // Custom debug view setup. if (Config.debug) { this.debugView.modes({ hidden : true }); } } }); <</script>>
<<if _action === 3 && _range === 1>> <<divider 'enemy'>> <p> <<= either("The bug bites you, <<DMG 1 8>>.","The insect rends you with its claws, <<DMG 2 5>>.")>> </p> <<elseif _range === 1>> <<divider 'moveback'>> <p> The massive insect scuttles back. </p> <<range 1>> <<elseif _range gt 1 && $enhealth lt 50 && _action == 2>> <<divider 'buff'>> <p> The swarm buzzes around the massive scarab, healing it for <b> 15 HP</b>. </p> <<set $enhealth += 15>> <<elseif _range gt 1>> <<divider 'enemy'>> <p> <<= either("The bug spits acid at you, <<DMG 1 5 'acid'>>. <<set _acid += 4>>","The cloud of insects rends you, <<DMG 3 5>>")>> </p> <</if>>
<<run setup.editRoom({content: 'SecretRoom'})>> /* Make secret room default location for the passage once seen */ <p>Find inner access key!</p> <<a 'Back' goto 'Game' id 1>><</a>>
<<widget 'ShopGrid'>> <<if _args[0] === 'sell'>> <<set _pool = $equip.concat($weapons,$storage)>> <div @class="_pool.length > 3 ? 'gridsmall' : 'center'" id="gridsell"> <<if !_pool.length>> <p>You have nothing to sell.</p> <<else>> <<for _item range _pool>> <<itemsell _item>> <</for>> <</if>> </div> <<else>> <<set _pool = State.variables[_args[0]], _ref = _args[0]>> <<if !_pool.length>> <p>There is nothing more to _args[1].</p> <</if>> <div @class="_pool.length > 3 ? 'gridsmall' : 'center'" @id="'grid'+_args[1]"> <<for _item range _pool>> <<if _args[1] === 'buy'>> <<itembuy _item>> <<else>> <<itemloot _item>> <</if>> <</for>> </div> <</if>> <</widget>>
<p> You make out a slender silhouette. It turns with a delayed mechanical jerk to face you. <br> The ragged automaton walks toward you. </p> <<a 'Fight it.' id 1>> <<fight setup.Auto 'rand'>> <<goto 'Combat'>> <</a>>
<p> You come across another large mechanical bug of the same kind you already defeated. <br> It stands up on its hind legs and hisses menacingly. </p> <<a 'Fight it!' id 1 goto 'Combat'>> <<fight setup.MomBug 'rand'>> <</a>>
<<widget 'divider'>> <<if $enhealth>> <<run let output = "<div class='divider'><hr>"; switch ( _args[0] ){ case 'enemy' : output += `<img @src="setup.locLoad('enemydiv')">`; break; case 'free': output += "<div class='divCenter'><div class='AP' style='border-radius:0;background-color:black'/></div>"; break; case 'movefor': output += "<div style='font-size:2.5em;margin-bottom:.1em;'>⇑</div>"; break; case 'moveback': output += "<div style='font-size:2.5em;'>⇓</div>"; break; case 'stun': output += "<div style='font-size: 2.5em;font-family: 'Stick No Bills', sans-serif;font-weight: bold;'>!</div>"; break; case 'buff': output += "<div style='font-size:3em;'>+</div>"; break; case 'doubleback': output += "<div style='font-size:3em; margin-bottom:-.15em; transform:rotate(180deg)'>⇮</div>"; break; case 'grapple': output += "<div style='font-size:3em;margin-bottom:.15em;'>⇮</div>"; break; case 'drone' : output += `<img @src="setup.locLoad('dronediv')">`; break; default: output += "<div class='divCenter'><div class='AP' style='border-radius: 0;'/></div>"; }; output += '</div>'; $('#fight').wiki(output); >> <</if>> <</widget>>
<<set setup.editRoom = function(newObject) { $rooms[$pos] = Object.assign(clone($rooms[$pos]), newObject); }>> <<widget 'clear'>> <<switch $rooms[$pos].type>> <<case 'Enemy'>> <<set setup.editRoom( {type: $enemy.loot? 'Loot' : 'Empty', content: "<p>The enemy lies on the ground, lifeless.</p><<= _scrapmessage? _scrapmessage : ''>>", item: $enemy.loot? setup.addAffix($enemy.loot.random()) : '' } )>> <<case 'Elite'>> <<set setup.editRoom( {type: 'Loot', content: 'The enemy lies on the ground, lifeless.', item: setup.Upgrades.advanced.random() } )>> <<case 'Boss'>> <<set setup.editRoom( {type: 'Exit', content: "You defeated the millipede, this is where the adventure ends for now... <br><br> <h3>...THANK YOU...</h3> <br> ...for playtesting this alpha version! I hope you didn't encounter too many bugs, or at least not of the game-breaking variety. <br> Updates and new content will come very soon. I had to cut out a good number of features, enemies and items to package this version into a somewhat polished game. <br><br> Thank you again for your time <3 <br><br> Maliface "} )>> <<case 'Exit'>> <<set setup.editRoom( {type: 'Exit', content: 'The remains of your destroyed foe liter the ground. Up ahead, domed tunnel leads you ever deeper into the under city.<br><<a "Next level" goto "Game">><<set $lvl ++>><<include "Map gen">><</a>>'} )>> <<case 'Loot' 'Curio'>> <<set setup.editRoom( {type : 'Empty room', item : ''} )>> <</switch>> <</widget>>
<p> A destroyed maintenance bot lies in the center of the room. </p> <p> It seems scavengers have already taken the most valuable parts but you might be able to salvage some more. </p> <<adel "Search the wreck." id 1>> <<set setup.editRoom( {type : 'Empty room', content : 'The remnants of a maintenance bot litter the floor.' )>> <<app>> <<= either(' <<scrap `random(10,25)`>> ',' The bare carcass has been thoroughly scrapped, leaving nothing but rusted metal. ')>> <</adel>>
<p> An old crate sits in a corner, half buried under dusty rubble. The flaking paint bears the sigil of a long forgotten militia. </p> <<adel "See what's inside" id 1>> <<set _loot = setup.Upgrades.common.random()>> <<set setup.editRoom( {type: 'Loot', content: 'The room is empty aside from the weathered crate.', item : _loot} )>> <<app>> <p> The crate holds military equipment which is still usable. </p> <<itemloot _loot>> <</adel>>
<p> The room ahead is filled with the stench of blood and decay. </p> <p> A corpse lies face down in a puddle of murky blood. The man's tattered clothes have been torn to shreds in places, revealing deep wounds in the rotting flesh. </p> <<adel "Search the body." id 1>> <<set setup.editRoom( {type: 'Empty room', content: 'The dark shape of a body lies face down in a puddle of clotted blood.'} )>> <<app>> <p> <<= either(" The disgusting search yields a handful of scraps. <<scrap `random(15,25)`>> "," <<set _gain = random(5, 30), $money += _gain>> The gruesome search yields <b class='mo'>_gain</b>. <<trigger 'UIupdate'>> "," You don't find anything of value and dare not undertake a more thorough search. ")>> </p> <</adel>>
<p> The wreck of a rescue bot lies scattered in a corner. Corrosion has crept up the four-legged carcass yet the sealed compartment which holds medical equipment seems untouched. </p> <<adel 'Look for medical supplies.' id 1>> <<set setup.editRoom( {type: 'Loot', content: '<p>The destroyed rescue bot lies there.</p>', item : " <<adel 'Use the supplies.'>> <<health +15>> <<clear>> <<app>>You manage to heal for <b class='hp'>15</b> hp by using the emergency supplies. <</adel>> "})>> <<app>> <p> You unlatch the stained cover which reveals as pristine cache of medical supplies. </p> <<= $rooms[$pos].item>> <</adel>>
<br> Find a frame upgrade! <br><br> <<= either ('<<itemloot setup.IntegratedShield>>','<<itemloot setup.HPup>>','<<itemloot setup.ExtraCapacity>>')>>
<br> Find some advanced augments! <br><br> <<itemloot setup.AdvUpgrades.random()>>
<br> Find a crate containing a large amount of scraps. <br><br> <<adel "Open it" id 1>> <<clear>> <<append '#content'>> The crate contains a pile of old military-grade components.<br><<scrap 50>> <</append>> <</adel>>
<<if !$infected>> <br> The center of the room hold a curious pool of reflective liquid. Its surface shifts and shimmers as you approach. <br><br> <<adel "Step into the sleek substance." id 1>> <<clear>> <<append '#content'>> Billions of oil-coated nanomachines slip into your body, granting you renewed vigor. <</append>> <<set $infected = true>> <<set $healmodifier += 0.2>> <</adel>> <br> <<a "Destroy it." id 2>> To come... <</a>> <<else>> <br> You encounter another pool filled with a sleek nanomachine swarm. <br><br> <<adel "Step in." id 1>> <<append '#content'>> The living swarm repairs your body, healing you for 15 HP. <</append>> <<set $health += 15>> <<if $health gt $MaxHealth>> <<set $health = $MaxHealth>> <</if>> <<health>> <</adel>> <</if>>
<<widget "itemloot">> <<set _intro = _args[1]>> <<hex _args[0]>> <<itemget _args[0]>> /* Clear widget */ <<if passage() === 'Game'>> <<clear>> <</if>> /* Replaces item container with shadowhex, stops multi-looting */ <<if _intro>> <<run $('#'+_id).replaceWith($(`<div class="hex shadowhex" id="intro"/>`))>> <<run $('#intro').wiki("<<a '<b>Get going!</b>' goto 'Game'>><</a>>")>> <<else>> <<run $('#'+_id).replaceWith($(`<div class="hex shadowhex">${_args[0].name} acquired.</div>`))>> <</if>> /* Refreshes equipment tabs */ <<trigger 'loot'>> <</hex>> <</widget>>
<<widget 'lvl'>> <div style=' display: grid; grid-template-columns: 5fr 1fr; grid-template-rows: 1fr 1fr; width: 20em; justify-content: center; align-items: center; margin: .5em;'> <div style='grid-row-start: span 2;'> _args[2] : <<if State.getVar('_'+_args[0]) != State.getVar('$'+_args[0])>> <b class=red><<= '_'+_args[0]>></b> <<else>> <<= '_'+_args[0]>> <</if>> <br> Cost: <<= (_args[3]? _args[3] : 1)>><br> </div> <<if _exp gte (_args[3]? _args[3] : 1)>> <<but "⇑" style margin:.1em;>> <<set _exp -= (_args[3]? _args[3] : 1)>> <<set _modif to State.getVar('_'+_args[0])+_args[1]>> <<run State.setVar('_'+_args[0], Math.round(_modif*100)/100 )>> <<replace '#lvl'>><<include 'leveling'>><</replace>> <</but>> <<else>> <<but '⇑' style pointer-events:none;color:grey;border-color:grey;margin:.1em;>> <</but>> <</if>> <<if _exp lt $exp && State.getVar('_'+_args[0]) != State.getVar('$'+_args[0])>> <<but '⇓' style margin:.1em;>> <<set _exp += (_args[3]? _args[3] : 1)>> <<set _modif to State.getVar('_'+_args[0])-_args[1]>> <<run State.setVar('_'+_args[0], Math.round(_modif*100)/100 )>> <<replace '#lvl'>><<include 'leveling'>><</replace>> <</but>> <<else>> <<but '⇓' style pointer-events:none;color:grey;border-color:grey;margin:.1em;>> <</but>> <</if>> <</widget>>
<div style='grid-area: 1/1/2/3;margin:1em;'> XP available: _exp </div> <<lvl 'AP' 1 'Action point' 10>> <<lvl 'capacity' 1 'Extra augment slot' 5>> <<lvl 'weaponcapacity' 1 'Extra weapon slot' 5>> <<lvl 'regen' 1 'Regeneration' 2>> <<lvl 'health' 10 'Health' 2>> <<lvl 'shield' 5 'Shield' 2>> <<lvl 'DMGresist' 0.1 'Damage resistance'>> <<lvl 'healmodifier' 0.1 'Healing modifier'>> <<lvl 'rangemodifier' 0.1 'Ranged damage'>> <<lvl 'cqcmodifier' 0.1 'Melee damage'>> <<lvl 'elecmodifier' 0.1 'Electric damage'>> <<lvl 'blastmodifier' 0.1 'Blast damage'>> <<lvl 'weaponsmodifier' 0.1 'Weapon damage'>> <<lvl 'allin' 0.05 'Extra attack chance'>>
<<widget 'refresh'>> <<replace '#game'>> /* Equivalent of PassageReady */ <<if !$Visited.includes($y+'-'+$x) && $health lt $MaxHealth>> <<set $health += $infested? Math.round(1.5*$regen) : Math.round($regen)>> <<trigger 'UIupdate'>> <</if>> <<set _id = 0>> /* Free movement, overwritten in 'content' */ <<set $move = true>> <<include 'Content'>> <<include 'Map'>> <<set $Visited.pushUnique($y+'-'+$x)>> <</replace>> <</widget>>
<<if !tags().includes('combat')>> <h2>Rare blast arm</h2> <div class='EvenSpace'> <img @src="setup.BlastArm.texture"> <img @src="setup.BlastArm.icon"> </div> <h3>Damage</h3> <p> Close quarters: 35 <br> Short range: 15 </p> <h3>Modifiers</h3> Ranged, ammo type <h3>Effect</h3> <p>Close range attacks knock opponents back</p> <<else>> <<skill setup.BlastArm 'Fire rare blast arm'>> <<AP 1>> <<if _range === 1>> <<range +1>> <<append "#fight">> <p> You fire at point-blank range. The powerful blast <<EnDMG 1 35>>and knocks your opponent back <<ammo>> <<stun>> </p> <</append>> <<else>> <<append "#fight">> <p> The pellets hit your opponent at medium range, <<EnDMG 1 15 _rangemodifier>> <<ammo>> </p> <</append>> <</if>> <</skill>> <</if>>
/* Frame upgrades */ <<set setup.ExtraCapacity = { name: "Capacity upgrade", desc: {Effect : 'Increases upgrade capacity by <b>1</b>' }, texture: setup.locLoad('capupgrade'), type: "frame" , price: 500 , qual: 'rare frame', modif: {capacity : 1} }>> <<set setup.WeaponCapacity = { name: "Weapon capacity upgrade", desc: {Effect : 'Increases weapon capacity by <b>1</b>' }, texture: setup.locLoad('extrawep'), type: "frame" , price: 500 , qual: 'rare frame', modif: {weaponcapacity : 1} }>> <<set setup.OverchargeCore = { name: "Overcharge core", desc: {Effect : "<span>Grants <<hover>> <div class='AP'/> <<tip class 'red'>> + 1 Action Point <</hover>> each turn.</span>", Effect2 : "<span>Grants +1 Action Point (<div class='AP'/>) each turn.</span>" }, texture: setup.locLoad('overcore'), type: "frame" , price: 600 , qual: 'rare frame', modif: {AP : 1} }>> /* HP ups -----------------------------------------------------------*/ <<ni 'setup.HPup' `{ name: "Common health upgrade", desc: {Effect : "Increases <b class='hp'>HP</b> by 10."} , texture: setup.locLoad('HPup'), type: "frame" , price: 100 , qual: 'common frame', modif: {MaxHealth : 10, health : 10}}`>> <<ni 'setup.AdvHPup' setup.HPup `{ name: "Advanced health upgrade", desc: {Effect : "Increases <b class='hp'>HP</b> by 20."} , price: 180 , qual: 'adv frame', modif: {MaxHealth : 20, health : 20}}`>> <<ni 'setup.RareHPup' setup.HPup `{ name: "Rare health upgrade", desc: {Effect : "Increases <b class='hp'>HP</b> by 25."} , price: 200 , qual: 'rare frame', modif: {MaxHealth : 25, health : 25}}`>> <<ni 'setup.ArmoredCore' setup.AdvHPup `{ name: "Armored core", desc: {Effect : "Increases <b class='hp'>HP</b> by 5.<br>Increases damage resistance by 5%."} , price: 200 , modif: {MaxHealth : 5, health : 5, DMGresist : 5}}`>> <<ni 'setup.RegenCore' setup.AdvHPup `{ name: "Regen core", desc: {Effect : "Increases <b class='hp'>HP</b> by 5.<br>Increases regen by 2."} , price: 200 , modif: {MaxHealth : 5, health : 5, regen : 2}}`>> /* Nanomachine nest -------------------------------------------------*/ <<set setup.NanoNest = { name: "Nanomachine nest", desc: {flavor : 'In cybernetic organs, swarms of nanomachines coalesce at certain points, not unlike animal white cells.', Effect : "<p>Increases regeneration by <b class='hp'>1</b>.</p>" } , texture: setup.locLoad('nanonest'), type: "frame" , price: 120 , qual: 'common frame', modif: {regen : 1}}>> <<ni 'setup.AdvNanoNest' setup.NanoNest `{ name: "Advanced nanomachine nest", desc: {flavor : '<p>In cybernetic organs, swarms of nanomachines coalesce at certain points, not unlike animal white cells.</p>', Effect : "<p>Increases regeneration by <b class='hp'>2</b>.</p>" } , price: 220 , qual: 'adv frame', modif: {regen : 2}}`>> /* Shields ----------------------------------------------------------*/ <<ni 'setup.IntegratedShield' `{ name: "Common shield upgrade", desc: {Effect : "Increases shield by <b class='sh'>5</b>"} , texture: setup.locLoad('shieldupgrade'), type: "frame" , price: 100 , qual: 'common frame', modif: {shield : 5} }`>> <<ni 'setup.AdvIntegratedShield' setup.IntegratedShield `{ name: "Advanced shield upgrade", desc: {Effect : "Increases shield by <b class='sh'>10</b>"} , price: 180 , qual: 'adv frame', modif: {shield : 10} }`>> <<ni 'setup.RareIntegratedShield' setup.IntegratedShield `{ name: "Rare shield upgrade", desc: {Effect : "Increases shield by <b class='sh'>15</b>"} , price: 250 , qual: 'rare frame', modif: {shield : 15} }`>>
<<if $hasFought.includes('Automaton')>> <p> Another strange automaton lies on the ground in front of you. Its metal chest is caved in and its limbs torn off. </p> <<else>> <p> A heavily damaged automaton lies on the ground. <br> Its design is unlike any robot you have encountered, it is built crudely from mismatched parts and components. </p> <</if>> <<adel "See what you can salvage" id 1>> <<set _loot = setup.Upgrades.random()>> <<set setup.editRoom( {type: 'Loot', content: 'The damaged robot lies still.', item : _loot} )>> <<app '#content'>> <p>Its construction is straightforward but not without an elegant simplicity. <br> You manage to scavenge usable hardware. </p> <<itemloot _loot>> <<set $AutoAware = true>> <</adel>>
<p> The corridor ahead is filled with the thick stench of decaying matter mixed with machine oil. Destroyed cyberbugs clutter the ground together with the occasional animal carcass. </p> <p> Gnawed power cables hang from the ceiling and the panelled walls are sleek with grease. </p> <p> The paths leads to a darker chamber. </p> <<a "Go in" id 1 goto 'Millipede2'>> <</a>>
Fight the quickdraw boss! <<a "Do it!" id 1>> <<fight setup.Boss>> <<goto 'Combat'>> <</a>>
As you walk through the underworld, you hear the steady scraping of metal mandibules. Further ahead, a cyberbug is gnawing on an animal carcass. It hasn't noticed you. <<a 'Attack it.' id 1 goto 'Combat'>> <<set $surprise = 1>> <<fight setup.CyberBug 'rand'>> <<set setup.editRoom( {type: 'Enemy', content: 'CyberBug'} )>> <</a>>
<p> You discover Meka's hidden shop. </p> <<a "Go in." id 1 goto "MekasShop">> <</a>> <<set setup.editRoom({type : 'Shop'})>>
<<set $CDrone = $MDrone = $HDrone = 0>> <<ni 'setup.CombatDrone' `{ name: "Combat drone", skill: "Combat_drone", action: "Combat_drone_action", desc : { flavor : "<p>A fully autonomous drone, most effective at close range.</p>", Damage : "<b>Close quarters</b> : 3 x 4" + "<br>" + "<b>Short</b> : 2 x 4" + "<br>" + "<b>Medium</b> : 4", Modifiers : "Drone damage", Uses : 1, Name : "<<input text 'setup.CombatDrone.name' placeholder setup.CombatDrone.name maxlength 25>>" }, icon: setup.locLoad('dronedeploy'), boxart: setup.locLoad('combatdrone'), dir : 'setup.CombatDrone', price: 200 , qual: 'adv', type: 'drone' , on: true, modif: {CDrone : 1}}`>> <<ni 'setup.MissileDrone' setup.CombatDrone `{ name: "Missile drone", skill: "Missile_drone", action: "Missile_drone_action", desc : { flavor : "<p>Fires long range guided missiles.</p>", Damage : "2 x 8", Range : "Medium, long.", Modifiers : "Drone damage", Uses : 1, Name : "<<input text 'setup.MissileDrone.name' placeholder setup.MissileDrone.name maxlength 25>>" }, dir : 'setup.MissileDrone', texture: setup.locLoad('missiledroneitem'), boxart : setup.locLoad('missiledrone'), modif: {MDrone : 1}}`>> <<ni 'setup.HealerDrone' setup.CombatDrone `{ name: "Healer drone", skill: "Healer_drone", action: "Healer_drone_action", desc : { flavor : "<p>The healer drone supplies repairs and protection.</p>", Effect : "If damage, heals you for <b class='hp'>6</b> HP." + "<br>" + "Grants <div class='block'>1</div> block otherwise.", Modifiers : "Drone affinity", Uses : 1, Name : "<<input text 'setup.HealerDrone.name' placeholder setup.HealerDrone.name maxlength 25>>" }, dir : 'setup.HealerDrone', boxart: setup.locLoad('healerdrone'), modif: {HDrone : 1}}`>>
<<charge 'CDrone'>> <<skill setup.CombatDrone 'Deploy <<= setup.CombatDrone.name>>'>> <<set _last = 'buff'>> <<AP 1>> <<set _CDrone -->> <<if !_CDrone>> <<set _totskills.delete(_item)>> <</if>> <<trigger 'skillboxRefresh'>> <<append '#fight'>> <h3><<= setup.CombatDrone.name>> deployed</h3> <</append>> <<set _activeDrones.push(setup.CombatDrone)>> <<trigger 'droneRefresh'>> <</skill>>
<<if !tags().includes('combat')>> <h2>Missile drone</h2> <img @src='setup.MissileDrone.icon'> <p>The autnomous drones fires missiles best fit for long range engagements.</p> <h3>Range</h3> Medium, long <h3>Damage</h3> 2 x 8 <h3>Modifiers</h3> Explosives, drone damage <h3>Uses</h3> 1 <h3>Name</h3> <<input text 'setup.MissileDrone.name' placeholder setup.MissileDrone.name maxlength 25>> <<else>> <<charge 'MDrone'>> <<skill setup.MissileDrone 'Deploy <<= setup.MissileDrone.name>>'>> <<if _AP>> <<set _last = 'buff'>> <<AP 1>> <<set _MDrone -->> <<if !_MDrone>> <<set _totskills.delete(_item)>> <</if>> <<trigger 'skillboxRefresh'>> <<append '#fight'>> <p> - <<= setup.MissileDrone.name>> deployed - </p> <</append>> <<set _activeDrones.push(setup.MissileDrone)>> <<trigger 'droneRefresh'>> <</if>> <</skill>> <</if>>
<<divider 'drone'>> <p> <<= _currentDrone.name>>: <br> <<if !_currentDrone.on>> This drone is inactive. <<elseif _range === 1>> The drone cannot fire at such a close range. <<else>> The drone fires two guided missiles and <<EnDMG 2 8 _droneDMG $blastmodifier>>. <</if>> </p>
<<if !tags().includes('combat')>> <h2>Healer drone</h2> <img @src='setup.HealerDrone.icon'> <p>Deploys an autonomous drone that heals you at the end of each turn.</p> <h3>Modifiers</h3> Drone affinity <h3>Uses</h3> 1 <h3>Name</h3> <<input text 'setup.HealerDrone.name' placeholder setup.HealerDrone.name maxlength 25>> <<else>> <<charge 'HDrone'>> <<skill setup.HealerDrone 'Deploy <<= setup.HealerDrone.name>>'>> <<if _AP>> <<set _last = 'buff', _HDrone -->> <<AP 1>> <<if !_HDrone>> <<set _totskills.delete(_item)>> <</if>> <<trigger 'skillboxRefresh'>> <<append '#fight'>> <p> - <<= setup.HealerDrone.name>> deployed - </p> <</append>> <<set _activeDrones.push(setup.HealerDrone)>> <<trigger 'droneRefresh'>> <</if>> <</skill>> <</if>>
/*<<charge 'associatedVar' 'extra' 'buff'>> */ <<widget "charge">> <<set _total = _args[1] ? Math.round(State.variables[_args[0]]*$extrause) : State.variables[_args[0]]>> <<set _style = (_args[2] === 'buff' || !_item.damage)? 'ammo buff' : 'ammo'>> <div class='charges'> <<for _m = _total, _num = State.temporary[_args[0]]; _m gt 0; _m-->> <<if _num gte _m>> <div @class='_style'></div> <<else>> <div @class='_style' style='background-color:transparent;'></div> <</if>> <</for>> </div> <</widget>>
<<widget 'skill' container>> /* Figure out if skill is usable*/ <<set _skill = {possible : false}>> <<if _blinded && _range gt 1>> <<set _skill.error = 'You are <b>blinded</b> and cannot use ranged skills.'>> <<elseif _range lt _args[0].rmin>> <<set _skill.error = 'The enemy is too close to use this skill.'>> <<elseif _range gt _args[0].rmax>> <<set _skill.error = 'The enemy is too far for the attack to reach.'>> <<elseif _item.ap gt _AP>> <<set _skill.error = 'Not enough AP, this action costs <<= _item.ap>> action points.'>> <<elseif !_AP>> <<set _skill.error = 'No AP.'>> <<else>> <<set _skill.possible = true>> <</if>> <<capture _skill>> <<set _skillKey = _args[3]?_args[3]:_skillID>> <<if typeof _args[0] === 'object'>> /* Combined link + attack widget*/ <<a " <<= _args[2]? _args[2] : ''>> <img @src=_args[0].icon> <div class='skillinfo'>_args[1]</div> " key `49+_i` class skill data-key `_i+1` style _args[4]>> <<if _AP gt 0 && $enhealth && _skill.possible>> <<append '#fight'>> _contents <</append>> <<else>> <<replace "#next">> <div class='warning'>_skill.error</div> <</replace>> <</if>> <</a>> <<else>> /* -------------- Supplied with image and description ---------------*/ <<a " <<= _args[2]? _args[2] : ''>> <img @src=_args[0]> <div class='skillinfo'>_args[1]</div> " key `49+_i` class skill data-key `_i+1` style _args[4]>> <<if _AP>> <<if _item.effect>> <<run $('#fight').wiki(_item.effect)>> <</if>> _contents <</if>> <</a>> <</if>> /* Possible indicator */ <<if _item.ap lt 1 && _skill.possible>> <div class='rangelight hollow'/> <<elseif _skill.possible>> <div class='rangelight'/> <<if _item.ap === 2>> <div class='rangelight'/> <</if>> <<else>> <div class='rangedead'/> <<if _item.ap === 2>> <div class='rangedead'/> <</if>> <</if>> <</capture>> <</widget>> /* <<skill object 'skillprompt' [extradisplay] [displayedkey] [inline styling]>> <<skill 'image URl' 'skillprompt' [specialID] [displayedkey] [inline styling]>> */
<<script>> Macro.add('on', { tags : null, handler() { if (!this.args[0]) { return this.error(`Missing event name.`); } else if (typeof this.args[0] !== 'string'){ return this.error(`Event name must be a string, reading: ${typeof this.args[0]}.`); } let trig = this.args[0].split(','), onInit = true; const content = this.payload[0].contents, attributes = this.args.slice(2); trig = trig.map(event => event.trim()); // Create element, apply attributes let container = $(document.createElement(this.args[1] ?? 'span')).addClass(`macro-${this.name}`); for (let i = 0; i < attributes.length;i++) { if (typeof attributes[i] === 'object'){//JQuery style object container.attr(attributes[i]); } else { // Simple pairs container.attr(attributes[i], attributes[i+1]); i++; } } if (container.attr('oninit')){ onInit = eval(container.attr('oninit')); container.removeAttr('oninit').attr('data-oninit', onInit); } // Apply listener for each event name trig.forEach(event => { if (Config.debug) { console.log(`Listener added for ${event}.`); } customEvents.pushUnique(event); $(document).on(event, function() { container.empty().wiki(content); }); }) // Wikify on passage load, unless onInit is false onInit ? container.wiki(content) : null; container.appendTo(this.output); } }); // Triggers custom event Macro.add('trigger', { handler() { if (this.args[0] === undefined || this.args[0] === '') { return this.error(`Missing event name.`); } else if (typeof this.args[0] !== 'string'){ return this.error(`Event name must be a string, reading: ${typeof this.args[0]}.`); } let trig = this.args[0].split(','); trig = trig.map(event => event.trim()); // Triggers each event supplied trig.forEach(event => { $(document).trigger(event); if (Config.debug) { console.log(`Triggered custom event: ${event}.`); } }) } }); // Cleans custom events on passage transition (stops them from stacking) window.customEvents = []; $(document).on(':passageinit', function () { customEvents.forEach(event => $(document).off(event)); customEvents = []; }); <</script>>
The pain feedback from implants is dulled on purpose. Sharp at first, it quickly turns into a numb itch in the limb. It serves as a reminder that the implant needs fixing. Most advanced weapons can be interfaced with. Manual action is replaced by advanced servos which increases timing and accuracy.
<<widget 'EnemyUI'>> /* Top bar */ <div class="infobar"> /* Turn counter */ <<on 'UIupdate'>>Turn : _turn<</on>> /* Main enemy display */ <<on 'EnemyUpdate' 'div' id 'enemyHUD'>> <span id='enUIleft'> /* Health */ <<hover 'b' class 'enskill'>> Health: $enhealth <<swap>> $enhealth / $enemy.health <</hover>> /* Stuns */ <<if _enstun>> <<hover 'b' class 'enskill'>> Stunned <<swap>> For _enstun action<<= _enstun gt 1? 's':''>> <</hover>> <</if>> /* DoT */ <<if Object.values($enemy.DoT).reduce((a, b) => a + b, 0)>> <b class='enskill'><span> <<for _key, _dot range $enemy.DoT>> <<if _dot>> <b @class="'DoT '+ _key">_dot</b> <</if>> <</for>> </span></b> <</if>> <<if $enemy.block>> <b class='enskill'> <span>Block: $enemy.block</span> </b> <</if>> </span> <div class='enemyPortrait'> <<if $enemy.texture>> <img @src='$enemy.texture'> <<else>> ENEMY<br><br><br>PICTURE <</if>> </div> <span id='enUIright'> /* Skills and traits */ <<if $enemy.skill>> <<for _ensk range $enemy.skill>> <<capture _ensk>> <<hover 'b' class 'enskill'>> _ensk.name <<swap>> _ensk.desc <</hover>> <</capture>> <</for>> <</if>> </span> <</on>> /* Range display */ <<on 'rangeChange, rangeRefresh' 'span' style 'display:grid'>> Range: <<= setup.ranges[_range-1]>> <<but '⇣' class rangeBut>> <<set settings.showRange = !settings.showRange, Setting.save() >> <<trigger 'rangeRefresh'>> <</but>> <<if settings.showRange>> <div class='unfoldRange'> <<for _i, _r range setup.ranges>> <span @class="_i+1 === _range ? 'highlight' : 'grey'"> _r </span> <</for>> <<but '⇡' class rangeBut>> <<set settings.showRange = !settings.showRange, Setting.save() >> <<trigger 'rangeRefresh'>> <</but>> </div> <</if>> <</on>> </div> <</widget>>
<div id="passages"></div> <div id='leftbar' data-passage="leftbar"></div> <div id='rightbar' data-passage="rightbar"></div> <div data-passage="lighting" style='display:grid'></div>
<<if tags().includes('initscreen')>> ...loading... <<elseif tags().includes('Menu')>> Combat Test - Menu <<elseif tags().includes('combat')>> Combat Test - Combat <<else>> Combat Test <</if>>
<<widget "hex" container>> <<if _args[0]>> /* Empty elements in the rarity arrays aren't displayed */ /* Handles the ID issue */ <<set _id ++>> <<capture _id, _price>> /*------------------------------Link---------------------------------*/ <<a ' <span class="hexinfo"><<= _args[1]? _args[1] : _args[0].name>></span> <<if _args[0].texture>> <img @src=_args[0].texture> <<else>> <<= _args[0].name>> <</if>> <<if _price>><b class=mon>₦ _price</b><</if>> ' class `_args[0].qual+' hex'` data-dir _args[0].dir id _id>> _contents <</a>> /* -----------------------Right click listener-----------------------*/ <<done>> <<run $('#'+_id).contextmenu((e) => { setup.itemDesc(e.currentTarget); return false; })>> <</done>> <</capture>> <</if>> <</widget>>
<<on 'mapRefresh' 'div' class 'map' style `'grid-template-columns: repeat(' + $MaxX + ', 1fr); grid-template-rows: repeat(' + $MaxY + ', 1fr);'` >> <<for _i, _room range $rooms>> <<run if (typeof $rooms[_i] === 'object') { _classes = []; _classes.push(_room.geometry); if ($visited.includes(_i)) { _classes.push('visited'); } if (_room.connect.includes('connectDown')) { _classes.push('connectDown'); } if (_room.connect.includes('connectRight') && $rooms[_i+1].type !== 'corridor') { _classes.push('connectRight'); } if (_room.type === 'Terrain') { _classes.push('terrain'); } _classes = _classes.join(' '); }>> <<if _i === $pos>> <div @class="'room activeRoom '+_classes"> YOU </div> <<elseif _room === 'Obstacle'>> <div></div> <<elseif $roomSeen.includes(_i)>> /* Is close or visited */ <div @class="'room '+_classes" @data-pos='_i'> <<= setup.printRoom(_room)>> </div> <<else>> <div @class="'room '+_classes" @data-pos='_i'/> <</if>> <</for>> <</on>> <style> #arrowBox { position: absolute; bottom: 0; display: grid; grid-template-columns: repeat(3,1fr); margin: auto; font-size: 2em; } #arrowBox > a { background-color: var(--transblack); margin: 0; padding: .25em; } </style>
/* Fast init for testing, to remove in final version*/ <<set $t = 0.05>> <div id='blackScreen'> <div id='initSpin'></div> <span style=position:absolute;> <<if Save.slots.has(0)>> <p>Save 0 is available</p> <<a '<b>Start from where you left off</b>' key settings.yes>> <<run Save.slots.load(0)>> <<run setup = clone($setup)>> <<unset $setup>> <</a>> <<a '<b>Fresh start</b>' goto 'init spin' key settings.no>> <<run Save.slots.delete(0)>> <</a>> <<else>> <<timed `$t+'s'`>> <span class='load'>Welcome</span> <<next>> <<silently>> <<include "Items init">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading augments...</span> <</replace>> <<next>> <<silently>> <<include "Passive items">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading passive items...</span> <</replace>> <<next>> <<silently>> <<include "Frame upgrades">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading frame upgrades...</span> <</replace>> <<next>> <<silently>> <<include "Weapons">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading weapons...</span> <</replace>> <<next>> <<silently>> <<include "Consumable items">> <<include "Story items">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading consumables...</span> <</replace>> <<next>> <<silently>> <<include "Drones init">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading drones...</span> <</replace>> <<next>> <<silently>> <<include "Enemies init">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading enemies...</span> <</replace>> <<next>> <<silently>> <<include "enemy affixes">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading enemy affixes...</span> <</replace>> <<next>> <<silently>> <<include "Pools init">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Loading shop pools...</span> <</replace>> <<next>> <<silently>> <<include "Map setup">> <</silently>> <<replace '.macro-timed'>> <span class='load'>Building map...</span> <</replace>> <<next>> <<replace '.macro-timed'>> <span class='load'>Cleaning floors...</span> <</replace>> <<next>> <<replace '.macro-timed'>> <span class='load'>Generating rooms...</span> <</replace>> <<next>> <<silently>> <<include "Map shuffle">> <</silently>> <<replace '.macro-timed'>> <span class='error'>ERROR</span> <</replace>> <<next>> <<replace '.macro-timed'>> <span class='error'>Aborting...</span> <</replace>> <<next>> <<replace '.macro-timed'>> <<if recall('hasSeenInit') || $cheat>> <<a '<b>Welcome back!</b>' goto 'Welcome' id 'link'>> <</a>> <<else>> <<a '<b>Welcome!</b>' goto 'Welcome' id 'link'>> <<set memorize('hasSeenInit', true)>> <</a>> <</if>> <</replace>> <<run $('#initSpin').animate({opacity:0}, 2500)>> <</timed>> <</if>> </span> </div>
<<script>> /*! <<checkvars>> macro for SugarCube 2.x */ // version check ! function() { "use strict"; if ("undefined" == typeof version || "undefined" == typeof version.title || "SugarCube" !== version.title || "undefined" == typeof version.major || version.major < 2) throw new Error("<<checkvars>> macro requires SugarCube 2.0 or greater, aborting load"); window.checkvar = 0; Macro.add("checkvars", { handler: function() { // toString function, processes the objects and indents them function toString(value, indent) { var baseType = typeof value; switch (baseType) { case "number": return isNaN(value) ? `NaN: ${String(value)}` : isFinite(value) ? String(value) : "Infinity"; case "string": return JSON.stringify(value); default: if ("object" !== baseType || null == value) return String(value); var objType = Object.prototype.toString.call(value); if ("[object Date]" === objType) return '(object: Date, value: "' + value.toISOString() + '")'; if ("[object RegExp]" === objType) return "(object: RegExp, value: " + value.toString() + ")"; var opener, closer, result = [],indentText = " "; return indent || (indent = ""), ("[object Set]" === objType || value instanceof Set) && (value = Array.from(value)), Array.isArray(value) ? (opener = "[\n", closer = "\n" + indent + "]", value.forEach(function(p, i) { result.push(indent + indentText + i + " ⇒ " + toString(value[i], indent + indentText)) }), Object.keys(value).forEach(function(p) { /^\d+$/.test(p) || result.push(indent + indentText + toString(p) + " ⇒ " + toString(value[p], indent + indentText)) })) : "[object Map]" === objType || value instanceof Map ? (opener = "{\n", closer = "\n" + indent + "}", Array.from(value).map(function(kv) { result.push(indent + indentText + toString(kv[0], indent + indentText) + " ⇒ " + toString(kv[1], indent + indentText)) })) : (opener = "{\n", closer = "\n" + indent + "}", Object.keys(value).forEach(function(p) { result.push(indent + indentText + toString(p) + " ⇒ " + toString(value[p], indent + indentText)) })), opener + result.join(",\n") + closer } } // Var types setup var dialog, storyvars = Object.keys(State.variables), tempvars = Object.keys(State.temporary), setupvars = Object.keys(setup), settvars = Object.keys(settings); const v = { type: [State.variables, State.temporary, setup, settings], keys: [storyvars, tempvars, setupvars, settvars], but: [`State variables (${storyvars.length})`,`Temporary variables (${tempvars.length})`,`Setup objects (${setupvars.length})`,`Setting objects (${settvars.length})`], name: [`State variables: ${storyvars.length}`,`Temporary variables: ${tempvars.length}`,`Setup objects: ${setupvars.length}`,`Setting objects: ${settvars.length}`], sigil: ['$','_','setup.','settings.'] }; // Display function function displayVars(index){ var tbody = dialog.querySelector('table tbody'); $(tbody).empty(); v.keys[index].sort(function(a, b) { return Util.isNumeric(a) && Util.isNumeric(b) ? Number(a) - Number(b) : a.localeCompare(b) }); for (var i = -1; i < v.keys[index].length; i++) { if (i === -1) { var tr = document.createElement("tr"), td = document.createElement("td"); $(td).attr('colspan', '2') .attr('text-align', 'center').attr('style', 'width:50em;'); td.innerHTML = '<h3>'+v.name[index]+'</h3>', tr.appendChild(td), tbody.appendChild(tr); } else { var tr = document.createElement("tr"), tdName = document.createElement("td"), tdValue = document.createElement("td"); tdName.textContent = v.sigil[index] + v.keys[index][i], tdValue.textContent = toString(v.type[index][v.keys[index][i]]), tr.appendChild(tdName), tr.appendChild(tdValue), tbody.appendChild(tr) } } }; if (dialog = UI.setup("Variables", "checkvars"), 0 === Object.keys(v.keys).length) return dialog.innerHTML = "<p><em>No $variables currently set…</em></p>", void UI.open(); //Populates dialog with buttons + table let container = jQuery(document.createElement('div')); container.attr('id','macro-checkvars-buttons'); $(dialog).append(container); for (let i = 0; i < v.name.length; ++i) { jQuery(document.createElement('button')) .addClass(`macro-${this.name}-btn-${i}`) .ariaClick( { namespace : '.macros', role : 'button' }, function () { displayVars(i); window.checkvar = i; }) .text(v.but[i]) .appendTo(container); } $(dialog).append('<table><tbody></tbody></table>') + (/applewebkit|chrome/.test(Browser.userAgent) ? "" : '<div class="scroll-pad"> </div>'); //Dialog opens on state variables displayVars(checkvar? checkvar : 0); UI.open() } }) }(); <</script>>
<<if $rooms[$pos].type === 'Shop'>> /* Has seen shop */ <<a "Visit Gregor's shop." key settings.yes goto "GregorsShop">> <</a>> <<else>> <p>In a corner, you notice a sturdy metal door bearing a faded sign which spells:</p> <h2>Gregor's Cafardnaum</h2> <<a "Bang on the door." key settings.yes>> <<set setup.editRoom({type : 'Shop'})>> <<app '#content'>> <p>You slam your first against the heavy door which gives off a loud metallic echo.</p> <p>A camera whirs faintly in the darkness, then a distorted voice.</p> <b class='grey'>"A customer at last! Would you like to see the merchandise?" <br> Just a second. </b> <p>Sharp clicking comes through the hidden speaker, then the door swings slowly on its hydraulic hinges.</p> <<a "Go in." key settings.yes goto "GregorsShop">> <</a>> <</a>> <</if>>
<p> The destroyed carcass of a cyberbug lies in a corner. Seems they are not at the top of the foodchain after all. </p> <<adel "Search the wreck." id 1>> <<app '#content'>> <p>Digging through the mechanical entrails, you salvage a few useful components.</p> <<scrap `random(10,15)`>> <<clear>> <</adel>> <<if $infected>> <<adel "Absorb nanomachines." id 1>> <<app '#content'>> <p>As you lay your hand upon the damaged shell, a thick black liquid oozes from the bug's internal structure. The oily substance climbs ups your arm and seeps into you augmented body.</p> <<health 10>> <</adel>> <</if>>
<<script>> Macro.add('newitem', { handler() { if (this.args.length === 0){ return this.error(`No argument supplied, <<item>> needs at least a name to function.`);} let newObj = {}, name = this.args[0]; if (typeof name !== 'string'){ return this.error(`The object name must be a string. Currently: ${typeof name}.`);} //Loop through supplied objects, assigning their properties to newObj for (let i = 1;i < this.args.length;i++){ if (typeof this.args[i] === 'object'){ Object.assign(newObj, this.args[i]); } else { return this.error(`'${this.args[i]}' is not an object nor can it be parsed into one.`); } } let reference = name.split('.'); if (reference.length > 1){ //Reference has dots in it (setup.variable)... switch(reference[0]){ case 'setup': setup[reference.slice(-1)] = clone(newObj); break; case 'settings': settings[reference.slice(-1)] = clone(newObj); Setting.save(); case 'State': State.setVar(name, clone(newObj)); break; default: return this.error(`Invalid or unsupported namespace: '${name}'.`); } } else { //Reference is a single block ($variable)... switch(name[0]){ case '$': case '_': State.setVar(name, clone(newObj)); break; default: return this.error(`'${name}' is missing a sigil.`); } } } }); Macro.add('ni', 'newitem'); <</script>>
<<if $ammosynt>> <<set _ammosynt = false>> <<for _var range setup.VarsWithExtrause>> <<if State.getVar('$'+_var) && $ammosynt gt random(1,100)>> <<= '<<set _'+_var+'++>>'>> <<set _ammosynt = true>> <</if>> <</for>> <<if _ammosynt>> <<append '#fight'>> <p>Ammunition regained.</p> <</append>> <</if>> <</if>>
<<widget 'DroneMenu'>> <<on 'droneRefresh' 'ul' id 'dronemenu'>> <<for _index, _drone range _activeDrones>> <<capture _drone>> <li class='dronebox' @id='"drone"+_index'> <b> <<= _drone.name>> </b> <img @src='_drone.boxart'> <<but `_drone.on?'X':'V'`>> <<set _drone.on = !_drone.on>> <<trigger 'droneRefresh'>> <</but>> </li> <</capture>> <</for>> <</on>> <</widget>>
<<if _range === 4>> <<divider 'movefor'>> <p> The insect advances toward you. </p> <<range -1>> <<elseif _range === 1>> <<divider 'enemy'>> <p> The millipede bites you, <<DMG 1 8>>. </p> <<else>> <<divider 'enemy'>> <p> The insect launches quills from its body, <<DMG `4-_range` 3>>. </p> <</if>>
<p>Fight a small millipede.</p> <<a 'Fight it!' id 1>> <<fight setup.MinorMillipede>> <<goto 'Combat'>> <</a>>
<p> As you explore the dimly lit tunnels and corridors, you come across a tall, baroque building which looks perfectly out of place. </p> <p> A pair of ornate glass doors open on a maze-like interior of cluttered shelves. </p> <<a "Go in." id 1 goto "ShopMann">> <</a>> <<set setup.editRoom({type : 'Shop'})>>
<div class='EvenSpace'> /* -------------------------- Rep links! ----------------------------*/ <<a 'Weapons'>> <<replace '#display'>> <h3>WEAPONS</h3> <div class="grid"> <<for _item range [...setup.Weapons, setup.Gunblade, setup.Katana]>> <<itemloot _item>> <</for>> </div> <</replace>> <<trigger 'leftclickdesc'>> <</a>> <<a 'Rare upgrades'>> <<replace '#display'>> <h3>RARE UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.rare>> <<itemloot _item>> <</for>> </div> <</replace>> <<trigger 'leftclickdesc'>> <</a>> <<a 'Advanced upgrades'>> <<replace '#display'>> <h3>ADVANCED UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.advanced>> <<itemloot _item>> <</for>> </div> <</replace>> <<trigger 'leftclickdesc'>> <</a>> <<a 'Common upgrades'>> <<replace '#display'>> <h3>NORMAL UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.common>> <<itemloot _item>> <</for>> </div> <</replace>> <<trigger 'leftclickdesc'>> <</a>> <<a 'Frame upgrades'>> <<replace '#display'>> <h3>FRAME UPGRADES</h3> <div class="grid"> <<for _item range [...setup.Frame.common, ...setup.Frame.advanced, ...setup.Frame.rare]>> <<itemloot _item>> <</for>> </div> <</replace>> <</a>> <<a 'Consumables'>> <<replace '#display'>> <h3>CONSUMABLES</h3> <div class="grid"> <<for _item range setup.Consumables>> <<itemloot _item>> <</for>> </div> <</replace>> <<trigger 'leftclickdesc'>> <</a>> </div> /* ------------------------- Default display -----------------------*/ <div id='display' style='display:inherit'> <h3>WEAPONS</h3> <div class="grid"> <<for _item range [...setup.Weapons, ...setup.SpecWeapons]>> <<itemloot _item>> <</for>> </div> <h3>RARE UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.rare>> <<itemloot _item>> <</for>> </div> <h3>ADVANCED UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.advanced>> <<itemloot _item>> <</for>> </div> <h3>NORMAL UPGRADES</h3> <div class="grid"> <<for _item range setup.Upgrades.common>> <<itemloot _item>> <</for>> </div> <h3>FRAME UPGRADES</h3> <div class="grid"> <<for _item range [...setup.Frame.common, ...setup.Frame.advanced, ...setup.Frame.rare]>> <<itemloot _item>> <</for>> </div> </div>
<<if _action === 3>> <<divider 'drone'>> <p> <<if _range lt 4>> The combat drone shoots you, <<if _range === 3>> <<DMG 1 6>> <<else>> <<DMG 2 6>> <</if>>. <<else>> The combat drone hovers silently, out of range. <</if>> </p> <<elseif _action === 4>> <<divider 'drone'>> <<if $enhealth lt $enemy.health>> <<set _heal = Math.round(6*randomFloat(0.8,1.2))>> <<set $enhealth = (_enhealth+_heal) gt $enemy.health? $enemy.health : ($enhealth+_heal)>> <p>The support drone heals the enemy for _heal HP.</p> <<else>> <<set $enemy.block ++>> <p>The support drone grants 1 block.</p> <</if>> <<elseif _action === 5>> <<divider 'drone'>> <<switch _range>> <<case 1>> <p>The drone releases an explosive blast, <<DMG 1 15>> and knocking you back.</p> <<range +1>> <<case 2>> <img src='https://cdn.discordapp.com/attachments/949715863479672913/1032221529401999431/drone_blast.png' class='actionBanner'> <p>The drone releases a weak explosive blast, <<DMG 1 5>>.</p> <<default>> <p>The blast drone hovers silently.</p> <</switch>> <<elseif $enemy.AP lt 5>> <<if _range === 1>> <<divider 'moveback'>> <p>The robot steps back.</p> <<range 1>> <<else>> <<divider 'buff'>> <<switch $enemy.AP>> <<case 2>> <p>The enemy deploys a combat drone.</p> <<case 3>> <p>The enemy deploys a support drone.</p> <<case 4>> <p>The enemy deploys a blast drone.</p> <</switch>> <<set $enemy.AP ++>> <</if>> <<elseif _range gt 1>> <<divider 'movefor'>> <p>The robot advances toward you.</p> <<range -1>> <<else>> <<divider 'enemy'>> <p> <<if _enemyuse>> A blade emerges from the robot's arm. <<set _enemyuse -->><br> <</if>> Your opponent thrusts in your direction, <<DMG 1 8>>. </p> <</if>>
<h2>Controls</h2> <p> Use the arrow keys, WASD or ZQSD to navigate the map. </p> <<set _posY = 1, _posX = 2>> <<on 'mapRefresh' 'div' id 'mapbox'>> <br> <div style = 'height:2em;'> <<if _posY !== 1>> <<a "⇑" key settings.keys.up class 'arrow'>> <<set _posY -->> <<trigger 'mapRefresh'>> <</a>> <</if>> </div> <br> <div style='width:2em;'> <<if _posX !== 1>> <<a "⇐" key settings.keys.left class 'arrow'>> <<set _posX -->> <<trigger 'mapRefresh'>> <</a>> <</if>> </div> <div class='map' style='grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr);margin:1em'> <<for _y = 1;_y lt 4;_y++>> <<for _x = 1;_x lt 4;_x++>> <<if _x === _posX && _y === _posY && _x === 2 && _y === 3>> <div class='room activeRoom'>YOU GOT IT</div> <<once 'passage'>><<trigger 'displayNew'>><</once>> <<elseif _x === _posX && _y === _posY>> <div class='room activeRoom'>YOU</div> <<elseif _x === 2 && _y === 3>> <div class='room'>GOT IT</div> <<else>> <div class='room'/> <</if>> <</for>> <</for>> </div> <div style='width:2em;'> <<if _posX !== 3>> <<a "⇒" key settings.keys.right class 'arrow'>> <<set _posX ++>> <<trigger 'mapRefresh'>> <</a>> <</if>> </div> <br> <div style='height:2em;'> <<if _posY !== 3>> <<a "⇓" key settings.keys.down class 'arrow'>> <<set _posY ++>> <<trigger 'mapRefresh'>> <</a>> <</if>> </div> <br> <</on>>
<<if Save.slots.has(0)>> <p>Save 0 is available</p> <<a '<b>Start from where you left off</b>'>> <<run Save.slots.load(0)>> <<run setup = clone($setup)>> <<unset $setup>> <</a>> <</if>> <p>Go to 'init spin' to get the full setup initialization</p> <<a '<b>Fresh start</b>' goto 'init spin'>> <</a>>
<<widget 'time'>> <<set $min += _args[0]>> /* Each period is 200 mins?*/ <<if $min gt 199>> <<set $time ++, $min -= 200>> <<if $time gt 7>> <<set $time = $time % 8>> <</if>> <</if>> <<for _i, _col range setup.palette[$time]>> <<set $color[_i] += _args[0]*((setup.palette[$time+1][_i]-setup.palette[$time][_i])/200)>> <</for>> <<run $('#lightsource').css('box-shadow','0 0 20vw 35vw rgb('+$color[0]+','+$color[1]+','+$color[2]+')')>> <</widget>>
<<if !tags().includes('Menu')>> <<on 'spotChange' 'div' id 'lightgrid'>> <div id="lightsource"></div> <<for _spot = 0; _spot lt $spotmax;_spot++>> <div class='spotlight'></div> <</for>> <</on>> <</if>>
/* In combat item use */ <<if $player.inventory.length>> <<on 'consume' 'div' class 'side' id 'Consumables'>> <<for _consu range $player.inventory>> <<if _consu.sit !== 'noncombat'>> <<capture _consu>> <<but '_consu.name' class 'consu'>> <<run Dialog.setup('','dialog'+_consu.qual), Dialog.wiki("<<consume _consu>>"), Dialog.open()>> <</but>> <</capture>> <</if>> <</for>> <</on>> <</if>>
<<widget 'diag' container>> <<run Dialog.setup( _args[0] , _args[1] ); Dialog.wiki( _contents); Dialog.open() >> <</widget>>
<<script>> Macro.add('toggle', { tags : ['case','all'], handler () { const varName = this.args[0], type = this.args[1], attributes = this.args.slice(2); const commonCode = this.payload.find(pay => pay.name === 'all'); let caseArray = []; //Return errors! if (varName === undefined) return this.error(`Toggle macro must be supplied with a variable: <<toggle '$variable'>>.`); if (varName && typeof varName !== 'string') return this.error(`Variable name needs to be a string, reading : '${typeof varName}'`); if (type && !['link','button'].includes(type)) return this.error(`Element type must be either 'link' or 'button', reading : '${type}'`); //Push 'case' tags content to caseArray this.payload.forEach(pay => { if (pay.name === 'case'){ caseArray.push(pay); } }) if (caseArray.length < 2) return this.error(`Toggle macro should have at least two cases, otherwise you can't toggle between them duh!`); //Fetch next payload based on current value function nextPayload () { const activePayload = caseArray.find(pay => pay.args[0] === eval(parse(varName))); const index = caseArray.indexOf(activePayload) +1; if (activePayload === undefined || index > caseArray.length-1) { return caseArray[0]; } else { return caseArray[index]; } } //Function that output the link element function linkBuilder(payload) { const value = payload.args[0], prompt = payload.args[1], innerAttr = payload.args.slice(2); if (value === undefined) return this.error(`Case value (<<case 'value'>>) is undefined.`); const link = $(`<${type === undefined || type === 'link'? 'a' : type}/>`); //Global attributes + tag-based ones for (let i = 0; i < attributes.concat(innerAttr).length;i++) { if (typeof attributes[i] === 'object'){// jQuery style object link.attr(attributes[i]); } else { //Simple pair link.attr( attributes[i], attributes[i+1]); i++; } } link.wikiWithOptions({ profile : 'core' }, (prompt ? prompt : value)).addClass(`macro-toggle-${value}`); link.ariaClick({ namespace : '.macros', role : type}, this.createShadowWrapper( () => { $.wiki(payload.contents); State.setVar(varName, value); if (varName.split('.')[0] === 'settings'){ //Settings need saving Setting.save(); } commonCode ? $.wiki(commonCode.contents) : null; //Swap for next payload! link.replaceWith(linkBuilder.call(this,nextPayload())); } ) ); return link; } $(this.output).append(linkBuilder.call(this, nextPayload())); } }) <</script>>
<p>The room ahead is filled with a stench of blood and decay.</p> <p> A corpse lies face down in a dark puddle of murky blood. The man's tattered clothes have been torn to shreds in places, revealing deep wounds in the rotting flesh. </p> <<adel "Search the body." id 1>> <<set setup.editRoom({type: 'Empty', content: 'The body lies motionless in a puddle of murky blood.'} ), _mon = random(5, 25), $money += _mon>> <<trigger 'UIupdate'>> <<app>> <p> The gruesome search yields <b class='mo'>_mon</b>. </p> <</adel>>
<p>An orange satchel lies open on the floor, seemingly abandonned by its previous owner.</p> <<adel 'Search' id 1>> <<set _loot = setup.DemoCharge>> <<set setup.editRoom( {type: 'Loot', content: '<p>The open satchel lies on the ground.</p>', item : _loot} )>> <<app '#content'>> <p> The tattered bag hold small tools and what you recognize as a demolition charge. A maintenance worker would have left them here at some point. </p> <<itemloot _loot>> <</adel>>
<<script>> Macro.add('input', { isAsync : true, handler() { let type = this.args[0], varName = this.args[1], varType, attributes = this.args.slice(2); // Broad error checks if (this.args.length < 2) { return this.error(`Missing input type or associated variable`); } if (typeof type !== 'string') { return this.error(`Input type is not a string, reading: "${type}"`); } if (typeof varName !== 'string' && !Array.isArray(varName)) { //Not a string nor array return this.error(`Invalid variable name, reading: "${varName}"`); } // Sensible data type based on input type function enforceType(inputValue) { const value = isNaN(Number(inputValue))||type === 'text'? inputValue : Number(inputValue); return value; } function inputBuilder(varkey, index) { if (varkey[0] === '$' || varkey[0] === '_') { varType = 'state'; } else if (varkey.split('.')[0] === 'setup') { varType = 'setup'; } else if (varkey.split('.')[0] === 'settings') { varType = 'settings'; } else { throw new Error(`Unrecognized variable type: "${varName}"`); } const input = jQuery(document.createElement('input')); // Applies attribute for (let i = 0; i < attributes.length;i+=2) { if (Array.isArray(attributes[i+1]) && index !== undefined){ //The array of vars is supplied with an attribute array if (varName.length !== attributes[i+1].length) { throw new Error(`Attribute values array must be the same length as variables array: [${varName}] !== [${attributes[i+1]}]`); } else { //Match by index input.attr(attributes[i], attributes[i+1][index]); } } else if (typeof attributes[i] === 'object'){ //JQuery style object input.attr(attributes[i]); i--; } else { // Simple pairs input.attr(attributes[i], attributes[i+1]); } } // ID setter if (index !== undefined){ //Multi outputs if (input.attr('id') === undefined){ // No supplied id var id = `${type}input-${Util.slugify(varkey)}-${index}`; } else { //Add index to custom id var id = `${input.attr('id')}-${index}`; } } else { //Single output var id = input.attr('id') === undefined ? `input-${type}-${Util.slugify(varkey)}` : input.attr('id'); } input.attr({ type : type, id : id , name : input.attr('name') ? input.attr('name') : `${type}input-${Util.slugify(varkey)}`, tabindex : 0}) .addClass(`macro-input`); // Attached label if needed if (input.attr('label')){ var label = jQuery(document.createElement('label')) .attr('for', input.attr('id')) .text(input.attr('label')); input.removeAttr('label'); } jQuery(input).on('change.macros', function() { State.setVar(varkey, enforceType(this.value)); if (varType === 'settings') { Setting.save(); } }) .on('keypress.macros', function (ev) { if (ev.which === 13) { // Enter keycode ev.preventDefault(); State.setVar(varkey, enforceType(this.value)); if (varType === 'settings') { Setting.save(); } if ($(this).attr('goto')){// To passage Engine.play($(this).attr('goto')); } } }); return [ label , input ]; } // Output to passage if (Array.isArray(varName)){ for (let i = 0; i < varName.length;i++){ inputBuilder(varName[i].trim(), i).forEach(elem => { elem ? elem.appendTo(this.output) : '' }); } } else { inputBuilder(varName.trim()).forEach(elem => { elem ? elem.appendTo(this.output) : '' }); } } }); <</script>>
<<done>> <<if navigator.userAgent.toLowerCase().match(/mobile/i)>> <<diag>> <h3>Warning</h3><br> <p>Mobile devices are not fully supported, both in term of display and features.</p> <p>Playing in landscape mode is advised for a better experience.</p> <<a 'Got it'>><<run Dialog.close()>><</a>> <</diag>> <</if>> <</done>>
<<script>> Macro.add('once', { tags : null, handler() { if (this.args.length === 0) { return this.error(`Missing scope argument: <<once 'passage/game' ['id']>>...`); } else if (this.args[1] && typeof this.args[1] !== 'string'){ return this.error(`ID argument must be a string, reading: '${typeof this.args[1]}'.`); } const scope = this.args[0] == 'passage'? State.temporary : State.variables, payload = this.payload[0].contents, ID = this.args[1]? this.args[1] : null; scope.onceMacro === undefined ? scope.onceMacro = [] : null; if (!scope.onceMacro.includes(ID? ID : payload)){ $(this.output).wiki(payload); scope.onceMacro.push(ID? ID : payload); } } }); <</script>>
/*<<applyAffix 'ondamage/death' 'name[otpional]'>>*/ <<widget 'applyAffix'>> /* Is a name supplied? if not use random */ <<set _affix = _args[1]? setup[_args[0]+'Affixes'].find(aff => aff.desc.name === _args[1]) : setup[_args[0]+'Affixes'].random()>> <<if typeof $enemy[_args[0]] === 'object'>>/* Is already an array */ <<set $enemy[_args[0]].unshift(_affix.effect), $enemy.skill.unshift(_affix.desc)>> <<elseif typeof $enemy[_args[0]] === 'string'>> /* Is a string */ /* Create array */ <<set _oldskill = $enemy[_args[0]], $enemy[_args[0]] = [_oldskill]>> <<set $enemy[_args[0]].unshift(_affix.effect), $enemy.skill.unshift(_affix.desc)>> <<else>> /* didn't have an associated field */ <<set $enemy[_args[0]] = [_affix.effect]>> <<if $enemy.skill === undefined>> <<set $enemy.skill = [_affix.desc]>> <<else>> <<set $enemy.skill.unshift(_affix.desc)>> <</if>> <</if>> <</widget>>
<<set setup.ondamageAffixes = [ {effect: "<<if random(1,4) === 4 && _range lte 2>><<set _acid += random(1,3)>><p class='small'>Corrosive fluid shoots toward you from the open wound.</p><</if>>", desc : {name : 'Caustic blood', desc : 'Close range attacks might coat the attacker in acid.'} }, {effect: "<<if !_enstun && random(1,6) === 6>><<set $enemy.block++>><p class='small'>The enemy blocks at the last second.</p><</if>>", desc: {name : 'Lightning reflexes', desc : 'Has a chance to block incoming attacks.'} }, {effect: "<<set $enemy.DMGresist += 2>>", desc: {name : 'Adaptative armor', desc : 'Damage taken increases resistance.'} }, {effect: "<<if $enhealth lt $MaxEnhealth/3>><<once 'passage'>><<set $enemy.AP ++>><p class='small'>The enemy grows more feisty.</p><</once>><</if>>", desc: {name : 'Second wind', desc : 'Gains 1 AP when HP goes below 30%.'} }, {effect: "<<set _enGlobal ++>>", desc: {name : 'Rage', desc : 'Gains 1% extra damage when hit.'} } ]>> <<set setup.ondeathAffixes = [ {effect: "<<include `$enemy.behav`>>", desc : {name : 'Last blow', desc : 'The enemy acts one last time before dying.'} }, {effect: "<<once 'passage'>><<set _vic = false, $enhealth = Math.round($MaxEnhealth/10)>><<divider 'enemy'>><p>The enemy revives with <b class='red'>$enhealth</b> HP.</p><<trigger 'EnemyUpdate'>><</once>>", desc: {name : 'Survivor', desc : 'Comes back to life at 10% health once.'} } ]>> <<set setup.oninitAffixes = [ {effect: "<<set _enemyAP ++>>", desc : {name : 'First blow', desc : 'The enemy as one extra AP on the first turn.'} }, {effect: "<<set $enemy.block ++>>", desc : {name : 'Low profile', desc : 'Starts with 1 block.'} }, {effect: "<<set _enGlobal += 10>>", desc : {name : 'Deadly', desc : 'Deals 10% extra damage.'} }, {effect: "<<set $enemy.DMGresist += 5>>", desc : {name : 'Tough', desc : 'Takes 5% less damage.'} }, {effect: "<<set $enhealth += $MaxEnhealth/10>>", desc : {name : 'Bulky', desc : 'Has 10% more HP.'} } ]>>
<<divider 'buff'>> <p> The plain automaton stands still. </p>
/* DoT after enemy action */ <<if $enemy.DoT.darts>> <p class='small'> <<= "The darts deal <<EnDMG 1 $enemy.DoT.darts '' 'orange' 'dot' 'noverb'>>.">> </p> <</if>> <<if $enemy.DoT.acid>> <p class='small'> <<= "The acid <<EnDMG 1 $enemy.DoT.acid '' 'acid' 'dot'>>.">> </p> <<set $enemy.DoT.acid-->> <</if>>
<<if $health !== $MaxHealth>> <<set _max = Math.min(($money-10)*(5/9), $MaxHealth-$health), _heal = 0, _price = 0>> <<inputbox range '_total' min 0 max $MaxHealth step any value $health id 'MekaHPslider'>> <<onchange>> <<if _total gt _max+$health>> <<run $('#MekaHPslider').val(_max+$health), _heal = _max>> <<set _price = Math.round(_heal*1.8+10)>> <<elseif _total lt $health>> <<run $('#MekaHPslider').val($health), _heal = 0>> <<set _price = 0>> <<else>> <<set _heal = _total - $health>> <<set _price = Math.round(_heal*1.8+10)>> <</if>> <<trigger 'HPchange'>> <</inputbox>> <<on 'HPchange' 'div' style 'padding:1.5em'>> HP: <b class='hp'><<= Math.round($health+_heal)>>/$MaxHealth</b> <br> Price: <b class='mo'>_price</b> <</on>> <<but 'Confirm'>> <<if _heal>> <<set $health += Math.round(_heal), $money -= _price>> <<trigger 'UIupdate'>> <<time `random(10,20)`>> <</if>> <<rep>> The machines comes to life and heals you for <b class='hp'> <<= Math.round(_heal)>></b>. <</but>> <<else>> You are already at full health. <</if>>
<<for _i, _item range _totskills>> <<capture _i, _item>> <<if typeof _item.skill === 'string'>> /* Is a passage name */ <div class='skillcontainer'> <<include _item.skill>> </div> <<else>> /* Is undefined AKA object properties do the job */ <div class='skillcontainer'> <<if _item.charge && State.temporary[_item.charge[0]] lt 1>> <div class="skill"> <img @src="_item.icon"> <div class='nocharge'> <<= _item.noMessage ?? 'No charges left.'>> </div> </div> <<elseif _item.cond && !eval(parse(_item.cond))>> <div class="skill"> <img @src="_item.icon"> <div class='nocharge'> <<= _item.noMessage ?? 'Item unusable.'>> </div> </div> <<else>> <<if _item.charge>> <<charge _item.charge[0] _item.charge[1]>> <</if>> <<skill _item `_item.skillname ?? _item.name` `_item.skillextra ?? ''`>> <<= _item.preAttack ?? ''>> <<AP `_item.ap ?? 1` `_item.divider ?? null`>> <p> <<= _item.prompt ?? 'The attack'>> <<if _item.damage>> /* Is an attack */ <<EnDMG `_item.num ?? 1` _item.damage `_item.modifiers ?? ''`>> <</if>> <<= _item.effect ?? ''>>. </p> <<if _item.charge>> /* Auto remove charges */ <<run State.temporary[_item.charge[0]]-->> <<trigger 'skillboxRefresh'>> <</if>> <</skill>> <</if>> </div> <</if>> <</capture>> <</for>>
<div id='blackscreen' onclick="SugarCube.setup.dismissSplashScreen()"> <div id='splashcontainer'> <div id='splashpicture'> <img @src='$enemy.texture'> </div> <div id='splashaffix'> <h2 class='splashname'> <<= $enemy.name>> </h2> <p> <<= $enemy.flavor>> </p> <<if $enemy.skill>> <<for _i, _ensk range $enemy.skill>> <p @style="'margin-left:'+(4.5+_i*2.5)+'vw'"> <<= "<b class='orange'>_ensk.name</b> : _ensk.desc">> </p> <</for>> <</if>> </div>
<<script>> Macro.add('times', { tags : null, handler() { const num = this.args[0], payload = this.payload[0].contents, oldI = State.temporary.i; if (typeof num !== 'number'){ return this.error(`Iteration value must be a number, reading:'${typeof num}'`); } try { //Run loop for (let i = 0; i < num; i++){ State.temporary.i = i; payload ? $(this.output).wiki(payload) : null; } } finally { //Ensure _i clean up oldI === undefined ? delete State.temporary.i : State.temporary.i = oldI; } } }); <</script>>
<<set _level = 0>> <<set _elevator = [" The sun is already hot over the busy Ibadan. Lone towers rise above the crowded rooves and covered streets, stretching as far as the eye can see. The doors of the elevator close with a pneumatic hiss. <img src='https://malifaciousgames.neocities.org/media/landscape1.png' style = 'position: absolute;left: -25vw;width: 100vw;z-index: -1;top: -10vh;'> ", " The narrow cabin shakes and trembles as it descends toward the strawling metropolis below. The unmistakable domed streets extend in every direction, cross and contort like veins spread between the larger surface hubs.", " Darkness swallows the cabin as it plunges into the masssive dome. The main level dome stands tall, brimming with life. People go about their lives bathed in the orange light.", "The elevator cabin lights up as it sinks underground. No more view, only your reflection under the crude electrical light.", "<<lights 2>> The elevator slows down and a large tunnel comes into view. Two rows of amber lights stretch into the darkness. The cabin doors open, letting the oily air in. <img src='https://malifaciousgames.neocities.org/media/underground.png' style = 'position: absolute;left: -25vw;width: 100vw;z-index: -1;top: -10vh;'> <<run $('button').empty().append('Step out.')>>"]>> <<set _elevatorShift = function () { $('#container') .animate({top: '0vh', opacity: 0}, 1500) .animate({top: '90vh'}, 10) .animate({top: '30vh', opacity: 1}, 1500); }>> <div id='container' style='position: absolute;top: 30vh;justify-self: center;max-width: 50vw;background-color: var(--transblack);box-shadow: 0 0 2em 2em var(--transblack);'> <span id='target'> <<= _elevator[_level]>> </span> <<but 'Down' key 's,arrowDown' style 'display:block;margin: auto;margin-top: 2em'>> <<if _level === 4>> <<goto 'Welcome'>> <<else>> <<set _level++>> <<run _elevatorShift(); setTimeout(() => { $('#target').empty().wiki(_elevator[_level]) },1500)>> <</if>> <</but>> </div>
Left bar animation: <<run let elems = $('#leftbar').children(), i = 0; let DismissMenu = setInterval(()=>{ $(elems[i]).css('position','relative') .animate({left:'-40vw'},200) .animate({left:'0'},200); i++; if (i > elems.length){ clearInterval(DismissMenu); console.log('Interval end') } }, 150);>> Loop for dark map navigation: <<for _i, _room range $rooms>> <<run if (typeof $rooms[_i] === 'object') { _classes = []; _classes.push(_room.geometry); if ($visited.includes(_i)) { _classes.push('visited'); } if (_room.connect.includes('connectDown') && $roomSeen.includes(_i+$MaxX)) { _classes.push('connectDown'); } if (_room.connect.includes('connectRight') && $roomSeen.includes(_i+1) && $rooms[_i+1].type !== 'corridor') { _classes.push('connectRight'); } _classes = _classes.join(' '); }>> <<if _i === $pos>> <div @class="'room activeRoom '+_classes"> YOU </div> <<elseif _room === 'Obstacle'>> <div></div> <<elseif $roomSeen.includes(_i)>> /* Is close or visited */ <div @class="'room '+_classes" @data-pos='_i'> <<= setup.printRoom(_room)>> </div> <<else>> /*<div @class="'room '+_classes" @data-pos='_i'/>*/ <div @class="'room hidden '+_classes" @data-pos='_i'/> <</if>> <</for>> Targeted sliders ---------------------------------------- <style> .inputcontainer { position: relative; display: flex; width: fit-content; align-items: center; } .inputmarker { position:absolute; height: 100%; width: 1em; pointer-events: none; border: var(--borderThickness) solid var(--orange); border-radius: var(--radius); padding: var(--borderThickness); z-index: -1; } </style> <div style='display: grid; gap: 2em; transform: rotate(90deg);'> <<set _scores = [], _inputs = []>> <<for _i = 0; _i lt 5; _i++>> <<capture _i>> <<set _scores.push(random(10)), _inputs.push(random(10))>> <span class='inputcontainer'> <div class='inputmarker' @style="'left:'+_scores[_i]*8.8+'%'"/> <<inputbox range '_inputs[_i]' max 10 value _inputs[_i] data-value _inputs[_i]>> <<onchange>> <<if _inputs.toString() === _scores.toString()>> <<run $('#sol').show()>> <<else>> <<run $('#sol').hide()>> <</if>> <</inputbox>> </span> <</capture>> <</for>> </div>
.buttonRow { display: flex; } .buttonRow button { width: 100%; border-bottom: 0; border-bottom-color: currentcolor; border-end-end-radius: 0; border-end-start-radius: 0; border-color: var(--grey); color: var(--grey); margin: 0 .1em; position: relative; padding: .5em 0; } button.activeBut { border-color: var(--orange); color: var(--orange); outline:0; z-index: 2; } .buttonRow button:first-child { margin-left: 0; } .buttonRow button:last-child { margin-right:0; } .buttonRow button::after { content: ''; position: absolute; width: 100%; top: 100%; left: 0; height: calc(var(--radius)*2); background-color: var(--background); z-index: 0; } button.activeBut::after { z-index: 2; } .buttonRow button:last-child::after { border-right: var(--borderThickness) solid; border-color: inherit; } .buttonRow button:first-child::after { border-left: var(--borderThickness) solid; left: calc(var(--borderThickness)*-1); border-color: inherit; } .buttonRow button:hover { border-color: var(--color); color: var(--color); box-shadow: none; } button.activeBut:hover { color: var(--orange); border-color: var(--orange); } .shop { border: var(--borderThickness) solid var(--orange); height: fit-content; min-height: 15em; border-radius: calc(var(--radius)*2); position: relative; box-shadow: 0 0 .5em .5em var(--background); display: grid; align-content: space-evenly; padding: 2em; background-color: var(--background); } #gridsell { overflow-y: scroll; padding-top: 2em; margin: .5em 0; }
#splashaffix * {text-align:left} h2.splashname:after, h2.splashname:before {display:none} h2.splashname {font-size: 10vh} #blackscreen { height: 100vh; width: 100vw; background-color: var(--transblack); position: fixed; top: 0; left: 0; z-index: 16; } .toTransparent {animation: toTransparent .5s ease} @keyframes toTransparent { 100% { background-color: transparent; outline-color: transparent; box-shadow: none; }} @keyframes slideright { 0% {left: -72vw;} 100% {left: 0;} } @keyframes slideleft { 0% {right: -44vw;} 100% {right: 0;} } #splashcontainer { position: absolute; height: 40%; width: 100%; top: 30%; left: 0; background-color: var(--background); z-index: 10; outline: 4px solid var(--orange); box-shadow: 0 0 5em 5em var(--background); display: grid; grid-template-columns: 2.5fr 1fr; } #splashpicture { height: 50vh; margin-top: -5vh; justify-self: revert; clip-path: polygon(0 0, 65% 0, 100% 100%, 0% 100%); z-index: 11; background-color: var(--background); border: 4px solid var(--orange); border-left: none; display: grid; align-items: center; justify-items: center; background: linear-gradient(65deg, var(--background) 50%, var(--orange) 60%); position: relative; animation: slideright .5s ease; } #splashpicture > img {height: 40vh; filter: drop-shadow(0 0 3em var(--background)) drop-shadow(0 0 2em var(--background)) drop-shadow(0 0 1em var(--background));} #splashaffix {margin-left: -15vw; animation: slideleft .5s ease; position:relative} #splashaffix > :nth-child(2) { margin-left: 2.5vw; font-family: 'Stick No Bills', sans-serif; font-size: 1.5em; margin-top: 0; margin-bottom: 0;}
#lightgrid { display: grid; grid-template-columns: 1fr 1fr; position: absolute; top: -10vh; justify-self: center; transform: perspective(20px) rotateX(-25deg) scaleY(25%); z-index: -3; height: 50vh; } .spotlight { height: 2em; border-radius: 35%; z-index: -1; margin: 5em; width: 0; box-shadow: 0 .5em 1em 1em RGB(255, 120, 0), 0 -.5em 1em 1em RGB(255,191, 0); } #lightsource { height: 1px; width: 1px; position: absolute; top: -30vh; right: 50%; border-radius: 100%; z-index: -1; visibility:hidden }
/* Text display */ #hp { color:var(--hp); font-weight:bold; overflow-wrap: break-word; } #sh { color: var(--shield); font-weight:bold; text-shadow: 0 0 1rem aqua,0 0 1rem aqua; } /* Bar */ .health-bar { display: grid; height: 20rem; grid-template-areas: "bar"; border: .2rem solid hsla(0, 0%, 100%, 0.1); border-radius: var(--radius); margin: 1em; width: 2rem; align-items: end; } .health { border-radius: var(--radius); grid-area: bar; height: var(--health-value); background: linear-gradient(#00aeae, var(--hp), #005353, var(--background)); justify-self: center; z-index: 9; width: 1.61rem; margin-bottom: .2rem; } .shield { border: .2rem solid var(--shield); border-radius: var(--radius); grid-area: bar; height: var(--shield-value); box-shadow: 0 0 .5rem .25rem aqua; z-index: 9; } .HPbarshadow { align-self: baseline; background-color: var(--background); grid-area: bar; width: 1.6rem; z-index: 9; justify-self: center; border-radius: var(--radius); } [style*="--shield-dmg"]{ border-radius: 0 0 var(--radius) var(--radius); border-top:none; } /* Style for number values */ .shieldbox { border: var(--borderThickness) solid hsla(0, 0%, 100%, 0.1); position: relative; display: inherit; padding: .75em; margin: 1em 0; border-radius: var(--radius); } .shieldbox b { display: block; padding: .5em 0; z-index: 10; } .shieldbox b:nth-child(2) { border-top: var(--borderThickness) solid; } .shielded { position: absolute; height: 100%; width: 100%; display: inherit; border: var(--borderThickness) solid var(--shield); box-shadow: 0 0 .5rem .25rem aqua; border-radius: inherit; bottom: 0; justify-self: center; } .shielded::after { content: attr(data-sh); position: absolute; top: 91%; justify-self: center; background-color: var(--background); padding: .15em .15em .5em .15em; color: var(--shield); box-shadow: 0 0 .1em .1em var(--background); } .shielded.dam::before { content: ''; width: 100%; position: absolute; background-color: var(--background); justify-self: center; bottom: 100%; height: .7em; border-radius: var(--radius) var(--radius) 0 0; }
#enemyHUD { border: var(--borderThickness) solid var(--orange); border-radius: 0 0 calc(var(--radius)*1.5) calc(var(--radius)*1.5); border-top: 0; background-color: inherit; padding: inherit; display: grid; grid-template-columns: 1fr 1fr 1fr; height: 6em; margin-top: -.5em; box-shadow:inherit; } .enemyPortrait { height: 10em; border: var(--borderThickness) solid var(--orange); border-top: none; border-radius: 0 0 var(--radius) var(--radius); background-color: inherit; border-bottom: none; margin: inherit; } .enemyPortrait img { max-height:100% } b.enskill { border: var(--borderThickness) solid var(--orange); border-radius: calc(var(--radius)/2); padding: .2em .5em; display: grid; box-shadow: 0 0 .2em .3em var(--background); margin: .25em 0; background-color:var(--background); height: max-content; font-size: 1em; margin-top: .35em; } b.enskill::before { content: ""; position: absolute; border-width: .8em; border-style: solid; z-index: 10; align-self: center; margin-left: -1.5em; border-color: transparent var(--orange) transparent transparent; } #enUIright , #enUIleft { height: inherit;} #enUIleft > b.enskill {transform: scale(-1, 1);} #enUIleft > b.enskill > * {transform: scale(-1,1);}
.infobar { position: absolute; top: 0; border-bottom: var(--borderThickness) solid var(--orange); border-radius: 0 0 calc(var(--radius)*1.5) calc(var(--radius)*1.5); padding: .5em; justify-self: center; background-color: var(--background); display: grid; grid-template-columns: 1fr 2.5fr 1fr; height: 1.5em; width: 66vw; box-shadow: 0 0 1.5em 1em #111; } .hidden {visibility:hidden;} .unfoldRange { display: grid; position: fixed; justify-self: center; border: var(--borderThickness) solid var(--orange); border-radius: 0 0 var(--radius) var(--radius); border-top: none; background-color: var(--background); padding: .4em; top: 0; } .rangeBut { position: absolute; justify-self: center; border: var(--borderThickness) solid var(--orange); border-bottom: 0; padding: 0 .5em; bottom: -2px; background-color: #111; height: .6em; border-radius: calc(var(--radius)*.5) calc(var(--radius)*.5) 0 0; outline: none; } .rangeBut:hover, .rangeBut:focus { background-color: #111; color: var(--white); border: var(--borderThickness) solid var(--orange); border-bottom: 0; outline: none; box-shadow: none; } .grey, .highlight {padding:.2em;} .grey {color:var(--grey)} .highlight {color:var(--white);font-weight:bold;font-style:normal} .highlight:before {content:'⇾'} .highlight:after {content:'⇽'}
#skillbox { border-top: var(--borderThickness) solid var(--orange); border-radius: calc(var(--radius)*2) calc(var(--radius)*2) 0 0; height: calc(var(--skillSize)*1.35); display:grid; padding:0.6em; margin:0em 0.2em 0 0.2em; background-color: var(--background); grid-auto-flow: column; grid-row-gap: .5em; } #skillbox a:hover, #skillbox a:focus { justify-content: center; display: flex; } /* Outer container, ensures alignement*/ .skillcontainer { justify-items: center; display: grid; align-items: center; align-self: flex-start; } .skill, .skillTall, .skillShort { position:relative; border: var(--borderThickness) solid var(--orange); outline: 2px solid black; margin: 0em 0.2em; display: flex; width: var(--skillSize); justify-content: center; transition-duration: .1s; background-color:#111; } .skillTall, .skillShort { border-radius:calc(var(--radius)*1.5) calc(var(--radius)*1.5) 0 0; border-bottom: none; } .skill { height: var(--skillSize); border-radius: calc(var(--radius)*1.5); } /* Display shortcuts on non-touch devices */ @media (hover: hover) { .skill::after, .skillTall::after, .skillShort::after { content: attr(data-key); position: absolute; border: var(--borderThickness) solid var(--background); outline: var(--borderThickness) solid var(--orange); border-radius: calc(var(--radius)*.5); color: var(--background); background-color: var(--orange); font-weight: bold; z-index:3; font-family: 'Stick No Bills', sans-serif; box-shadow: 0 0 4px 5px var(--background); } .skillTall::after, .skillShort::after { margin-top: -.9em; width: calc(var(--skillSize)/6.25); height: calc(var(--skillSize)/6.25); line-height: calc(var(--skillSize)/6.25);} .skill::after {top: calc(var(--skillSize)*.91); width: calc(var(--skillSize)/6.25); height: calc(var(--skillSize)/6.25); line-height: calc(var(--skillSize)/6.25);} .skill:hover, .skillTall:hover, .skillShort:hover, .skill:focus, .skillTall:focus, .skillShort:focus { border-color: var(--white); transition-duration: .2s; box-shadow: 0 0 .5em 0.25em aqua, 0 0 .25em .1em #b5f8ff; outline: 2px solid black; } .skill:hover:after, .skillTall:hover:after, .skillShort:hover:after { outline-color: var(--white); transition-duration: .1s; } } .skillTall {height: calc(var(--skillSize)*1.25);} .skillShort {height: var(--skillSize);} .skillinfo { visibility: hidden; position: absolute; background-color: rgba(0, 0, 0, 0.85); width: calc(var(--skillSize)*.8); box-shadow: 0 0 10px 5px rgb(0, 0, 0); justify-self:center; align-self:center; text-shadow: 0 0 10px black; z-index: 3; } .skillinfo>.skill {width:calc(var(--skillSize)*.8)} .skill img {height:100%;z-index:2} /*Images scales to skill size */ .skillTall img, .skillShort img { width: 100%; /*Images scales to skill width */ height: min-content; z-index: 2; } a:hover .skillinfo, a:focus .skillinfo {visibility:visible;} a:focus img.skill { border: 2px solid var(--white); transition-duration: .2s;} /* Range light under skill*/ .rangelight, .rangedead { height: .5em; width: 90%; border-radius: var(--radius); margin-top: .5em; } .rangelight { background-color: #b9ffff; box-shadow: 0 0 5px white, 0 0 10px aqua, 0 0 15px teal; outline: 2px solid teal; } .rangedead { outline: 2px solid hsla(0, 0%, 100%, 0.1); background-color: #171717; } .rangelight.hollow { background-color: #163535; outline: 2px solid #b9ffff; } a > .rangelight, a > .rangedead { position:absolute; bottom: 1em; } /* Skill covers for free actions, charges, best range and so on... */ .nocharge, .freeaction, .optirange, .charges { position: absolute; height: 99%; width: 99%; display: flex; align-items: center; justify-content: center; margin: .1em .3em; background-size: contain; background-repeat: no-repeat; border-radius: calc(var(--radius)*1.5) } .nocharge{ color:var(--orange); z-index:2; background-image: url("data:image/svg+xml,%3Csvg width='150' height='150' xmlns='http://www.w3.org/2000/svg'%3E%3Cg id='Layer_1'%3E%3Ctitle%3ELayer 1%3C/title%3E%3Crect rx='35' id='svg_2' height='149.68748' width='149.68749' y='0.3125' x='0.31249' fill-opacity='0.65' fill='%23000000'/%3E%3C/g%3E%3C/svg%3E"); } .freeaction { background-image: url("https://cdn.discordapp.com/attachments/949715863479672913/960961464343068712/freeoverlay.png"); } .optirange{ z-index:1; background-image: url("https://cdn.discordapp.com/attachments/949715863479672913/960961464573775952/optimaloverlay.png"); } /* Item charges widget, charges is container, ammo are the red pips */ .charges { display:grid; grid-template-columns:1fr; z-index:1; grid-gap:5%; height: calc(var(--skillSize)*.9); width: calc(var(--skillSize)*.96); margin-bottom: calc(var(--skillSize)/10); } .ammo { background-color: #ff000085; height: 100%; width: 95%; margin: auto; border-radius: calc(var(--radius)*.2); outline: calc(var(--borderThickness)/2) solid #ff0000c2; } .ammo.buff { background-color: #006c6c8c; outline: var(--borderThickness) solid #0092a2; } .ammo:first-child { border-radius: var(--radius) var(--radius) calc(var(--radius)*.2) calc(var(--radius)*.2); } .ammo:last-child { border-radius: calc(var(--radius)*.2) calc(var(--radius)*.2) var(--radius) var(--radius); } .ammo:only-child { border-radius: var(--radius); } /* Stun button, width is set through JS */ .stunbutton { display: flex; background-color: #111; z-index: 2; height: var(--skillSize); border-radius: calc(var(--radius)*1.5); margin: 0 0.2em; justify-content: center;} .stunbutton:hover {background-color: var(--transblack);}
#cheatmenu::-webkit-scrollbar { display: none; } #cheatmenu:before { content: 'C H E A T S'; writing-mode: vertical-rl; text-orientation: upright; position: fixed; width: 2vw; top: 37vh; } #cheatmenu { border: var(--borderThickness) solid var(--orange); border-right: none; position: absolute; display: grid; max-height: 80vh; right: -13vw; width: 16vw; border-radius: var(--radius) 0 0 var(--radius); transition-duration: .2s; z-index: 10; background-color: var(--transblack); row-gap: 2px; column-gap: 2px; align-items: center; justify-content:right; padding: .5em 0; overflow-y: scroll; overflow-x: clip; -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ } #cheatmenu input { margin: .2em 0; width: 12vw; border-radius: var(--radius) 0 0 var(--radius); border-right:0; } #cheatmenu:hover, #cheatmenu:focus { right:0; transition-duration: .2s; } #cheatmenu button { border-right: none; border-radius: 0; border-bottom-left-radius: inherit; border-top-left-radius: inherit; }
#dronemenu { position:fixed; right:0; top: 3em; width: 16vw;} .dronebox { border: var(--borderThickness) solid var(--orange); border-right: none; border-radius: var(--radius) 0 0 var(--radius); padding: 1em; margin: .5em 0 .5em 0; display: grid; grid-template-columns: 3fr 1fr; justify-items: baseline; background-color: var(--transblack); } .dronebox.active { box-shadow: 0 0 .5em 0.25em aqua, 0 0 .25em .1em #b5f8ff; outline: 2px solid black; border-color: var(--white); } .dronebox.active > * { border-color: var(--white); } .dronebox > img { max-width: 12vw; position: relative; left: -2vw; border-radius: var(--radius); border: var(--borderThickness) solid var(--orange); background-color: var(--background); } .dronebox > b { grid-column: span 2; justify-self: flex-start; }
/*Combat UI ---------------------------------------------------------*/ .passage[data-tags~="combat"] { display:grid; } #next { position: fixed; top: 63vh; font-weight: bold; justify-self: center; } /* Transorming text! (warning, HP after damage...) */ @keyframes flicker { 0% { opacity:0; } 20% { opacity:1; } 35% { opacity:0; } 53% { opacity:1; } 80% { opacity:0; } 100% { opacity:1; } } .flicker1 {animation:flicker .6s} @keyframes flicker2 { 0% { opacity:0; } 45% { opacity:1; } 53% { opacity:0; } 65% { opacity:1; } 89% { opacity:0; } 100% { opacity:1; } } .flicker2 {animation: flicker2 .8s} @keyframes flicker3 { 0% { opacity:0; } 15% { opacity:1; } 20% { opacity:0; } 32% { opacity:1; } 89% { opacity:0; } 100% { opacity:1; } } .flicker3 {animation: flicker3 .5s} .hidden {visibility:hidden} @keyframes vanishing { 0% { opacity:1; } 100% { opacity:0; } } .warning { color: var(--red); font-weight:bold; animation:vanishing 2.5s; opacity:0; } @keyframes blur { 0% { opacity:1;filter: blur(0px); } 100% { opacity:0;filter: blur(3px); } } .vanishing { animation:blur 4.5s; opacity:0; } /* Fight display */ .fightWrapper { position: absolute; border: var(--borderThickness) solid var(--orange); border-radius: calc(var(--radius)*1.5); z-index: -2; height: 60vh; border-top: 0; border-bottom: 0; width: 58vw; top: 0; justify-self: center; } #fight { position: fixed; bottom: 40vh; max-height: 60vh; z-index: -2; overflow-y: scroll; -ms-overflow-style: none; scrollbar-width: none; justify-self: center; width: 60vw; text-shadow: 0 0 .5em var(--background); } #fight::-webkit-scrollbar { display: none; } #fight > h3 { margin: 1em; font-size: 1.7em; } #fight img {max-height: 25vh;} .actionBanner {max-width: 40vw;} #enhealth { position: fixed; width: fit-content; font-weight: bold; bottom: 30vh; padding: 4px; justify-self: center; } #CombatUI { position: fixed; bottom: 0; display: grid; justify-items: center; grid-template-columns: repeat(5,1fr); grid-template-rows: repeat(2,1fr); height: 16em; width: min-content; align-items:end; justify-self:center; } .combatUI .macro-timed {display:none;} #APcounter { grid-column: span 5; width: fit-content; padding:0 1em; border-top: var(--borderThickness) solid var(--orange); border-radius: calc(var(--radius)*1.5); background-color: var(--transblack); } .AP, .APspent { height: .5em; width: .5em; border-radius: 100%; display: inline-block; margin: .25em .35em; } .APspent{ outline: 2px solid hsla(0, 0%, 100%, 0.1) } .AP { background-color: #b9ffff; box-shadow: 0 0 5px white, 0 0 10px aqua, 0 0 15px teal; outline: 2px solid teal; }
/* Grid sizes and values */ .grid , .gridsmall { display: grid; margin: 2em 0; width: max-content; justify-self: center; grid-auto-rows: 9.8em; margin: 2.5em 0; } @media (min-width: 2100px) and (max-width: 10000px) { .grid { grid-template-columns: repeat(14,1fr); } .grid>.hex:nth-child(13n-12) { grid-column: span 3; justify-self: end; }} @media (min-width: 1800px) and (max-width: 2100px) { .grid { grid-template-columns: repeat(12,1fr); } .grid>.hex:nth-child(11n-10) { grid-column: span 3; justify-self: end; }} @media (min-width: 1500px) and (max-width: 1800px) { .grid { grid-template-columns: repeat(10,1fr); } .grid>.hex:nth-child(9n-8) { grid-column: span 3; justify-self: end; }} @media (min-width: 1200px) and (max-width: 1500px) { .grid { grid-template-columns: repeat(8,1fr); } .grid>.hex:nth-child(7n-6) { grid-column: span 3; justify-self: end; }} @media (min-width: 1000px) and (max-width: 1200px) { .grid { grid-template-columns: repeat(6,1fr); } .grid>.hex:nth-child(5n-4) { grid-column: span 3; justify-self: end; }} @media (max-width: 1000px) { .grid { grid-template-columns: repeat(4,1fr); } .grid>.hex:nth-child(3n-2) { grid-column: span 3; justify-self: end; }} /*Grid small*/ .gridsmall { grid-template-columns: repeat(6,1fr); } .gridsmall>.hex:nth-child(5n-4) { grid-column: span 3; justify-self: end; } .EvenSpace { display: flex; justify-content: space-evenly; } .center { display: flex; justify-content: center; margin: 2em 0; } .hex { display: grid; height: var(--hexSize); width: var(--hexSize); transition: opacity 0.2s; margin: 3px; background-size: contain; position: relative; place-items: center; place-self: center; } /* Span 2 doesn't break other grid elements */ .grid>.hex, .gridsmall>.hex{ grid-column: span 2; } .hex:hover.shadowhex { background-image: none; color: var(--white); } .hex img { height: calc(var(--hexSize)*2/3); } .common { background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath stroke-width='3' fill='none' stroke='Gray' d='m2.0195,100.20661l41.94888,-97.71418l111.86367,0l41.94886,97.71418l-41.94886,97.71418l-111.86367,0l-41.94888,-97.71418z' id='svg_2' transform='rotate(90, 100, 100)'/%3E%3Cpath id='svg_1' d='m360.19501,109.03792l1.14591,0l0.3541,-0.54067l0.3541,0.54067l1.14591,0l-0.92706,0.33415l0.35411,0.54067l-0.92706,-0.33416l-0.92706,0.33416l0.35411,-0.54067l-0.92706,-0.33415z' stroke='%23000' fill='%23fff'/%3E%3C/g%3E%3C/svg%3E"); color:var(--grey); border-color:var(--grey); } .adv { background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath stroke-width='3' fill='none' stroke='DarkOrange' d='m2.0195,100.20661l41.94888,-97.71418l111.86367,0l41.94886,97.71418l-41.94886,97.71418l-111.86367,0l-41.94888,-97.71418z' id='svg_2' transform='rotate(90, 100, 100)'/%3E%3Cpath id='svg_1' d='m360.19501,109.03792l1.14591,0l0.3541,-0.54067l0.3541,0.54067l1.14591,0l-0.92706,0.33415l0.35411,0.54067l-0.92706,-0.33416l-0.92706,0.33416l0.35411,-0.54067l-0.92706,-0.33415z' stroke='%23000' fill='%23fff'/%3E%3C/g%3E%3C/svg%3E"); border-color:var(--orange); } .rare { background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath stroke-width='3' fill='none' stroke='rgb(215, 26, 26)' d='m2.0195,100.20661l41.94888,-97.71418l111.86367,0l41.94886,97.71418l-41.94886,97.71418l-111.86367,0l-41.94888,-97.71418z' id='svg_2' transform='rotate(90, 100, 100)' /%3E%3C/g%3E%3C/svg%3E"); color: var(--red); border-color:var(--red); } .spec {background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath stroke-width='3' fill='none' stroke='rgb(0,174,174)' d='m2.0195,100.20661l41.94888,-97.71418l111.86367,0l41.94886,97.71418l-41.94886,97.71418l-111.86367,0l-41.94888,-97.71418z' id='svg_2' transform='rotate(90, 100, 100)'/%3E%3Cpath id='svg_1' d='m360.19501,109.03792l1.14591,0l0.3541,-0.54067l0.3541,0.54067l1.14591,0l-0.92706,0.33415l0.35411,0.54067l-0.92706,-0.33416l-0.92706,0.33416l0.35411,-0.54067l-0.92706,-0.33415z' stroke='teal' fill='%23fff'/%3E%3C/g%3E%3C/svg%3E"); color: var(--spec); border-color:var(--spec); } /* Inner hex */ .hex .innerHex { background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath id='svg_1' d='m6.61768,100l40.021,-93.67643l106.72265,0l40.02099,93.67643l-40.02099,93.67643l-106.72265,0l-40.021,-93.67643z' stroke-width='2' stroke='rgb(215, 26, 26)' transform='rotate(90, 100, 100)' fill='none'/%3E%3C/g%3E%3C/svg%3E"); } /* Money amount in hex containers */ b.mon { color:#ffb300; position:absolute; z-index:5; text-shadow: 0px 0px 30px black,0px 0px 25px black,0px 0px 20px black,0px 0px 15px black,0px 0px 10px black,0px 0px 5px black; margin-top: 6em; } /* Hex tooltip + white boder, serves as hover/focus highlight */ .hex:hover { background-image: url("data:image/svg+xml,%3Csvg width='200' height='200' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Ctitle%3ELayer 1%3C/title%3E%3Cpath stroke-width='3' fill='none' stroke='SeaShell' d='m2.0195,100.20661l41.94888,-97.71418l111.86367,0l41.94886,97.71418l-41.94886,97.71418l-111.86367,0l-41.94888,-97.71418z' id='svg_2' transform='rotate(90, 100, 100)'/%3E%3Cpath id='svg_1' d='m360.19501,109.03792l1.14591,0l0.3541,-0.54067l0.3541,0.54067l1.14591,0l-0.92706,0.33415l0.35411,0.54067l-0.92706,-0.33416l-0.92706,0.33416l0.35411,-0.54067l-0.92706,-0.33415z' stroke='%23000' fill='%23fff'/%3E%3C/g%3E%3C/svg%3E"); text-shadow: 0px 0px 30px black,0px 0px 25px black,0px 0px 20px black,0px 0px 15px black,0px 0px 10px black,0px 0px 5px black; } .hexinfo {position:absolute; visibility:hidden; width: calc(var(--hexSize)*.8);} .hex:hover .hexinfo{visibility:visible} /* Size 2 items */ .s2::after { content: '2'; position: absolute; margin-top: calc(var(--hexSize)*.75); border: calc(var(--borderThickness)*1.5) solid; border-radius: 5px 5px 0 0; padding: calc(var(--hexSize)/35); border-bottom: none; font-weight: bold; } #ui-dialog-body.s2::after {display: none;} .s2:hover::after {border-color: var(--white);} .s2:active::after {border-color: inherit} /* Empty upgrade slot */ .slot { height: 15px; width: 15px; border-radius: 10em; background-color: black; outline: 3px solid Gray; box-shadow: 0px 0px 30px Teal,0px 0px 30px Teal,0px 0px 30px Teal; } .shadowhex:hover .slot { box-shadow: 0px 0px 30px Aqua,0px 0px 30px Aqua,0px 0px 30px Aqua; outline: 3px solid seashell; }
.macro-hover { display: inline-flex; position: relative; justify-content: center } .macro-hover-swap { cursor: default } .macro-hover-tip::after, .macro-hover-tip::before { content: ''; position: absolute; z-index: 10 } .macro-hover-tip { position: absolute; top: -1.75em; width: max-content; padding: 0 .5em; border-radius: calc(var(--radius)/2); display: inline-flex; justify-content: center; box-shadow: 0 0 .5em .45em var(--background); background-color: var(--transblack); z-index: 10; opacity: 0; transition: .25s; pointer-events: none; min-height: 1.75em; align-items: center; border-width: var(--borderThickness); border-style: solid; } .macro-hover-tip::before { border: .5em solid transparent; border-top-color: inherit; top: 1.85em } .macro-hover-tip::after { border: .5em solid transparent; border-top-color: #111; top: 1.6em } .macro-hover:hover > .macro-hover-tip { opacity: 100%; pointer-events: revert }
Find dead enemies as environment details, hinted at you not being alone. Nine years ago, Nigeria won the third federal war through the use of very advanced nano machines, capable of very fast repairs. The post-war world is flourishing and these microscopic nano machines have spread to most technologies and domains. These have solved the issue of wear since mechanical structures can be endlessly repaired as they wear down at a molecular scale. This is achieved by embedding a Integrated Structure Model into materials that can be then rebuilt accordingly. Research on general human healing are on their way... The forgotten flipside from the war was that desctructive nanomachines swarms were also developped and deployed, capable of destroying materials and boring through flesh in seconds. As such, the darts are a forbidden item based on hidden technology. Somehow, the new generation of nano machines is linked to former maintenance robots going feral. The Federation has spent millions on building a powerful robot militia to contain these wild robots to the depths (riflebot, brawlbot, sentry...). Corrupted machines attack most things on sight, either robotic or organic, and seem to try to feed on them. As you go deeper, you meet the First Born, an entity born from the nano machines' hive mind, fashion as to look like a woman, it is a swarm of oil-based robots. It claims to be an AI yet seems quite basic, the swarm only serves as a remote presence for the main brain. Alludes to having higher level sibblings (thus First Born). The Pupeteer is a mad engineer, obsessed by the idea of birthing life from simple parts. He is an uncanny character in that he doesn't recognize AIs as a possibility, relying rather on simplistic behaviours and technology. Motion, more than agency or free will, serves as a proof of life in his eyes. Was exiled from the surface society, conducted Gregor's full body transplant when he was condemned by a deadly form of cancer. It seemed Gregor wasn't aware the body would be one of a bug, had he known, he would rather have died... Three depth layers, each have their own shopkeeper (random), first boss is the millipede, a military grade machine from the war, lives as an apex predator in this new ecosystem. Five bosses? Robot gunslinger, assassin, pupeteer and First Born + Milli? First born and Pupeteer can be reasoned with, their paths do not end in fights (and the First Born is unkillable anyway). Fight bosses are Millipede, Gunslinger, assassin and Runaway AI... Nano machine corruption prevents you from using Meka's healing station, she instead offers you a medkit for free Presence in the depths is strictly forbidden -> encounter Efi while she's being taken in by a remotely operated riot bot. Option to attack it and free her, follow them toward an entrance point to the inner network, discover a few things about the way it works and keys... All three shopkeepers know about the inner network but only Shopmann has a key. Rewards you if you happen to kill Gregor. Can attack all the shopkeepers, Gregor fights back, Meka reaches for a gun but she's otherall very weak, Shopmann's front desk explodes and stuns you while he runs away.
Replace stack overflow with drug injectors. Like the tonic they drastically increase focus and metabolic rate, even in full frames the biological components still play a role on reflexes, awareness and pain resistance.
<<script>> Macro.add('hover', { tags : ['swap','tip'], handler() { const swap = this.payload.find(pay => pay.name === 'swap'), tip = this.payload.find(pay => pay.name === 'tip'), contAttr = this.args.slice(1); if (swap && !swap.contents) { //Empty <<swap>> has very problematic behavior, thus the error return this.error('<<swap>> tag has no content.'); } //Create outer + inner container const container = $(document.createElement(this.args[0]||'span')), innerCont = $('<span>').wiki(this.payload[0].contents); container.append(innerCont); // Catch capture mode! if (contAttr.includes('capture')){ var capture = contAttr.deleteAt([contAttr.indexOf('capture')+1])[0]; contAttr.delete('capture'); } function applyAttr(elem,array) { for (let i = 0; i < array.length;i++) { if (typeof array[i] === 'object'){//JQuery style object elem.attr(array[i]); } else { // Simple pairs elem.attr(array[i], array[i+1]); i++; } } return elem; } applyAttr(container, contAttr); if (tip) {//Create tip elem, add attributes var tipElem = $('<span>'); applyAttr(tipElem, tip.args).addClass('macro-hover-tip'); if (capture) {tipElem.wiki(tip.contents)}; container.append(tipElem); } if (swap) {//Add attributes to inner container (mostly for targetting) applyAttr(innerCont, swap.args); if (capture) { var shadowSwap = $(document.createDocumentFragment()).wiki(swap.contents), shadowCont = $(document.createDocumentFragment()).wiki(this.payload[0].contents); }; } innerCont.addClass('macro-hover-inner'); $(container).hover(this.createShadowWrapper(() => {//In if (swap) { innerCont.empty(); capture ? innerCont.append(clone(shadowSwap)) : innerCont.wiki(swap.contents); } if (tip) { tipElem.empty().wiki(tip.contents); } }), this.createShadowWrapper(() => {//Out if (swap) { innerCont.empty(); capture ? innerCont.append(clone(shadowCont)) : innerCont.wiki(this.payload[0].contents); } })); container.addClass('macro-hover').appendTo(this.output); } }); <</script>>
<<run $rooms.shuffle()>> <<set _gens ++>> /* Sets up possible connections */ <<run $rooms.forEach((room,i) => { if (typeof room === 'object') { room.connect = []; room.possible = []; room.index = i; if (typeof $rooms[i-$MaxX] === 'object') { room.connect.push('connectUp'); room.possible.push(i-$MaxX); } if ((i+1)%$MaxX && typeof $rooms[i+1] === 'object') { room.connect.push('connectRight'); room.possible.push(i+1); } if (typeof $rooms[i+$MaxX] === 'object') { room.connect.push('connectDown'); room.possible.push(i+$MaxX); } if (i%$MaxX && typeof $rooms[i-1] === 'object') { room.connect.push('connectLeft'); room.possible.push(i-1); } } })>> /* ------------------- Disconnect random rooms --------------------- */ <<run for (let i = 0; i < $MaxX*$MaxY*.2; i++) { const sIndex = random(0, $rooms.length), room = $rooms[sIndex]; if (random(0,1)) { const roomRight = $rooms[sIndex+1]; if (typeof room === 'object' && room.connect.includes('connectRight') ) { /* Vertical */ room.connect.delete('connectRight'); roomRight.connect.delete('connectLeft'); room.possible.delete(sIndex+1); roomRight.possible.delete(sIndex); } } else { const roomDown = $rooms[sIndex+$MaxX]; if (typeof room === 'object' && room.connect.includes('connectDown') ) { /* Horizontal */ room.connect.delete('connectDown'); roomDown.connect.delete('connectUp'); room.possible.delete(sIndex+$MaxX); roomDown.possible.delete(sIndex); } } }>> <<run _checkedRooms = [], _totRooms = $rooms.filter(r => typeof r === 'object'), setup.roomChecker(_totRooms.random().index) >> <<if _checkedRooms.length !== _totRooms.length>> <<include 'Map shuffle'>> <<else>> <<run console.log('Final generation! Took '+_gens+' passes.')>> <<include 'Map gen'>> <<run setup.Flicker()>> <</if>>
/*<<DMG number damage `modif/[modifs]` style type>>?*/ <<set setup.toNum = (arg) => { if (typeof arg === 'number') { return arg; } else if (typeof arg === 'string'){ return Scripting.evalTwineScript(arg); } else { return new error('Value to parse is neither a number nor a string...'); } }>> <<widget "EnDMG">> <<set _num = setup.toNum(_args[0])>> <<set _EnDMG = setup.toNum(_args[1])>> <<set _style = (_args[3] ?? 'orange')>> <<set _type = (_args[4] ?? 'default')>> <<set _noverb = _args.includes('noverb') ? true : false, _noS = _args.includes('noS') ? true : false>> /* Apply modifiers */ <<if typeof _args[2] === 'object'>>/* Is an array of modifiers*/ <<for _i, _mod range _args[2]>> <<set _mod = typeof _mod === 'number'? _mod : State.getVar(_mod)>> /* _mod is always a number*/ <<set _EnDMG *= (_mod+(_i*100))/(100+(_i*100))>> <</for>> <<elseif _args[2]>>/* A single modifier*/ <<set _mod = typeof _args[2] === 'number'? _mod : State.getVar(_args[2])>> <<set _EnDMG *= (_mod/100)>> <</if>> /* Heat modfier and DMGresist */ <<set _EnDMG *= (_heat-$enemy.DMGresist)/100>> <<if _type !== 'dot'>> /* Doesn't trigger on DoT */ <<triggerEffect 'ondamage'>> /*<<run $.wiki($player.onattack)>> Soon...*/ <<run if ($allin gt random(2500)){ _num += 3; } else if ($allin gt random(500)){ _num += 2; } else if ($allin gt random(100)){ _num++; }>> <</if>> /* ------------------------- Resolve attacks ----------------------- */ <<set _totDMG = 0, _blocked = [], _damage = []>> <<run for (let i = 0; i lt _num; i++) { /* Init dmg value */ let DMG = {value: 0, type : `${_type} ${_style}`}; if (_type === 'dot'){ DMG.value = _EnDMG; } else if ($enemy.block) { /* Block */ if ($ammotype === 'AP') { DMG.value = _EnDMG/2; DMG.type += ' shieldbreak'; } else { DMG.type += ' enblock'; $enemy.block --; } } else if ($CritChance +(_item.critChance ?? 0) gt random(1,100)) { /* Crit */ const critMod = ($CritMultiplier + (_item.crit ?? 0))/100; DMG.value = _EnDMG * randomFloat(0.8,1.2) * critMod; DMG.type += ' crit'; } else { DMG.value = _EnDMG * randomFloat(0.8,1.2); } if (DMG.value !== 0) { DMG.value = Math.max(1, Math.round(DMG.value-$enemy.plating)); _totDMG += DMG.value; _damage.push(DMG); } else { _blocked.push(DMG); } }>> /* ------------------------- Display damage ------------------------ */ <<set _output = ''>> <<run if(_blocked.length) { _output += ' remove<<= _noS? "" : "s">> <b class="enblock">'+ _blocked.length +'</b> block'+(_blocked.length gt 1? 's' : ''); if(_damage.length) { _output += ' and'; } }>> <<run _damage.forEach((DMG, i) => { if (i === 0 && !_noverb) { _output += ' deal<<= _noS? "" : "s">> '; } _output += `<b class='${DMG.type}'>${DMG.value}</b>`; if (i === _damage.length - 1) { /* last element */ _output += ' damage'; } else if (i === _damage.length - 2) { /* penultimate */ _output += ' and '; } else { _output += ', '; } })>> <<if _damage.length gt 1>> <<hover '' capture true>> _output <<swap>>deals <b @class="_style+' '+_type">_totDMG</b> total damage <</hover>> <<else>> <<= _output>> <</if>> /* Health removal */ <<set $enhealth -= Math.clamp(Math.round(_totDMG), 0, $enhealth)>> /* Updates enemy profile, timed for post-damage effects */ <<done>> <<trigger 'EnemyUpdate'>> <</done>> /* Victory or enhealth update */ <<if $enhealth === 0 && !_vic>> <<set _vic = true, $('#CombatUI a').ariaDisabled(true)>> /* setting _vic to false stops the victory widget */ /* timed makes it appears below action entry */ <<done>> <<if $enemy.ondeath>> <<triggerEffect 'ondeath'>> <<else>> <b>Your opponent collapses.</b> <</if>> <</done>> <<timed `settings.turnSpeed/3 + "s"`>> <<Victory>> <</timed>> <</if>> <</widget>>
<p> A large pillar stands in the center of the room, bundles of wires connect to it from the ceilling and run along its base. </p> <p> At chest height is a terminal. </p> <<adel 'Activate the machine.'>> <<run _checkedRooms = [], setup.scoutRooms($pos, $MaxX/2), setup.editRoom({type: 'Empty', content: 'The humming terminal goes with an amber light.'} ), >> <<app>>The dull screen lights up and displays what seems to a map of nearby rooms. <</adel>>
<<if $enemy.block>> /* As block, heals */ <<divider 'buff'>> <<set _heal = random(5, 10), $enemy.block--, $enhealth += _heal>> <<trigger 'EnemyUpdate'>> <p>The massive insect heals for <b class='red'>_heal</b> HP<<= $enemy.block ? '.' : ', then unfolds.'>></p> <<elseif $enhealth lt ($MaxEnhealth-15) && _turn%2>> <<divider 'buff'>> <p>The insect rolls itself into an armored ball.</p> <<set $enemy.block += 3>> <<elseif _range gt 2>> <<divider 'moveback'>> <p>The insect advances toward you.</p> <<range -1>> <<elseif _range === 2>> <<divider 'enemy'>> <p>The insect rolls into a ball and slams into you, <<DMG 1 10>> and knocking you to the ground.</p> <<set _ground = true>> <<else>> <<divider 'enemy'>> <p>The massive isopod slams you with it head, <<DMG 1 8>>.</p> <</if>>
<style> b {color: var(--red)} .passage {max-width: 45em} </style> <p>Coding, art and writing by me, <b>Maliface</b>.</p> <h3>THANKS</h3> <p>A big thank you to the Twine community for the help and lovely support. <br> Especially to: </p> <p> <b>TRBRY</b>, <b>Cyrus Firheir</b>, <b>Hituro</b>, <b>{G𝖜𝖊𝖓[♡].T𝖆𝖘𝖙𝖎𝖈}</b>, <b>SjoerdHekking</b>, <b>Manon</b>, <b>Leahiel</b>, <b>SleepyFool</b>, <b>Bodgan</b>... </p> <p> To <b>TheMadExile</b> for creating and keeping Sugarcube updated. </p> <p> To <b>Klembot</b> for doing the same with the Twine application. </p> <h3>MACROS</h3> <p> Are you a SugarCube dev yourself? <br> This game was created with the use various custom macros which I created to improve the Sugarcube workflow. I hope they can bring others the same utility I got from them. <<a 'GitHub' href 'https://github.com/MalifaciousGames/Mali-s-Macros'>><</a>> </p> <h3>CONTRIBUTE</h3> <p> Like the game and want to contribute? </p> <p> I have a <<a 'ko-fi account' href 'https://ko-fi.com/malifaciousgames' style 'display:contents'>><</a>>. <br>Any contribution is greatly appreciated. </p>
<<if $visited.length === 1>> The worn out ladder leads you down to a barely lit room. <<else>> You can barely see the old access ladder in the darkness. <</if>>
#arrowBox { display: grid; grid-template-columns: repeat(3,1fr); margin: auto; font-size: 2em; position: absolute; bottom: 0; background-color: var(--background); border: var(--borderThickness) solid var(--orange); border-radius: inherit; box-shadow: inherit; border-bottom: 0; visibility : hidden; }
<div/> <div id='innerBar'> <<smartbutton "Settings,about">> <<smartbutton "Upgrades">> <<smartbutton "Inventory">> <<smartbutton "Cheat" 'cheat'>> <<smartbutton "Bestiary" 'cheat'>> <<but '' data-content 'Restart'>> <<diag>> Any progress will be lost! <<a 'Confirm' goto 'init spin'>> <<run Dialog.close(), $.wiki('<<include StoryInit>>')>> <</a>> <</diag>> <</but>> <<if $cheat>> <<but 'Reload map'>> <<run $('#blackScreen').show(); $.wiki(Story.get('Map setup').text); $.wiki(Story.get('Map shuffle').text)>> <<timed .5s>><<goto 'Game'>><</timed>> <</but>> <<but 'Checkvars' key 'c'>> <<checkvars>> <</but>> <<but 'CheckRoomsFun'>> <<run _checkedRooms = [], setup.scoutRooms($pos, 7)>> <</but>> <</if>> /*<div class='side'> <img @src="setup.locLoad('transkey')"> <img @src="setup.locLoad('transkey')"> <img @src="setup.locLoad('transkey')"> </div>*/ </div> /* HP bar*/ <<on 'UIupdate' 'div' id 'outerBar'>> <<HP>> <<if tags().includes('combat')>> <div @class="_block?'block':'noblock'"> _block/$maxBlock </div> <<if _acid>> <p> Acid: <b class='acid'>_acid</b> </p> <</if>> <<else>> <b class="mo">$money</b> <b class="scp">$scraps</b> <</if>> <</on>>
#rightbar { position: fixed; right: 0px; top: 3em; width: 16vw; } #leftbar { position: fixed; top: 3em; width: 15rem; display: grid; align-items: center; transition: .3s; background-color: var(--transblack); box-shadow: 0 0 1em 1em var(--transblack); z-index: 15; grid-template-columns: 4fr 1fr; border: var(--borderThickness) solid var(--orange); border-left: none; border-radius: 0 var(--radius) var(--radius) 0; left: -10.5rem; padding-bottom: 1rem; } #leftbar:hover, #leftbar.unstowed { left: 0; } #leftbar b.mo::before, #leftbar b.scp:before { font-size: .8rem; display: block; } #leftbar b.mo:before {content:'Money:'} #leftbar b.scp:before {content:'Scraps:'} #leftbar b.mo, #leftbar b.scp {font-size:1.8rem;display: inline;} #innerBar { max-height: 90vh; position: absolute; top: -1rem; width: calc(10.5rem - var(--borderThickness)); display: flex; flex-direction: column; background-color: var(--background); box-shadow: 0 0 .5em .5em var(--background); } #innerBar > button { border-radius: 0 var(--radius) var(--radius) 0; transition-duration: .3s; width: inherit; border-left: 0; margin: .2em 0; display: inline-flex; align-items: center; height: 2.2em; } #innerBar > button::after { content: attr(data-content); position: absolute; transition: .3s; width: 0; text-align: right; } #innerBar > button:hover::after { width: 90%; } #innerBar > .side { border-right: var(--borderThickness) solid var(--orange); border-left: none; border-top: none; border-radius: 0 0 var(--radius) 0; } #outerBar { display: grid; gap: 1rem; justify-items: center; width: 4.5rem; }
Bundle of wires that supply the surrounding rooms with power Option to cut them. => blackout effect on the map + remove ceiling lights cannot see content of adjacent rooms higher payouts
Isopod behaviour usually non agressive, doesn't engage the player (maybe later, when frenzied) has innate damage resistance in combat: powerful head bash which pushes to ground weak bite rolls into ball, gaining block and healing (like the turret) doesn't flee, not nimble enough
<p> The floor ahead is littered in rubble of all kinds. Concrete, corroding steel, discarded items from the upper levels form an homogeneous mass under the layer of dust. </p> <p> A few recognizable shapes draw your attention. </p> <<adel 'Look closer.' id 1>> <<run setup.editRoom({content: '<p>The strange head lies on the floor where you last put it down.</p>', item : setup.head })>> <<app>> <p> You scavenge a few items of value, if only for their components. Augmented limbs lie here and there, heavily damaged. </p> <<scrap `random(5,15)`>> <p> As you scour the rubble, a rounded shape catch your sight. You pull the skull up to examine it. </p> <<itemloot setup.head>> <p> The disarticulated jaw hangs alongside the severed brain stem, bare connections appear where implant would normally sit. <br> <i>...total replacement...</i> <br> Is it what it looks like? Only a brain in a fully augmented body? </p> <</adel>>
<<set setup.Scraps = { name: "Scraps", desc: {flavor : "<i>One man's trash is the next man's pleasure</i><br><i>One man's pain is the next man's pleasure...</i>"+ "<p>Can be traded in shops for money.</p>", Amount : '$scraps' } , texture: setup.locLoad('scraps'), type: 'key', dir : 'setup.Scraps', qual: 'spec'}, setup.InnerNetworkKey = { name: 'Inner network key', desc: { flavor : " <<if $netAccess.aware>> <h2>Inner network key</h2> <p>Each key is unique and cannot be duplicated. <br>Grants access to the inner network.</p> <<else>> <<include 'netAccessDialog'>> <</if>> "} , type: 'frame', dir : 'setup.InnerNetworkKey', price: 1000, modif: {'netAccess.travel' : true}, qual: 'spec'}, setup.head = { name: "Scavenged skull", desc: {flavor : "<p>Can there even be <i>someone</i> in there?</p>"}, type : 'key', dir : 'setup.head', texture: setup.locLoad('skullitem'), modif: {skull : true}, qual: 'spec'} >> <<run console.log('stor')>>
<<set _rand = random(2), _dmg = random(12, 18)>> <p> The rifle-wielding robot is nowhere to be seen. </p> <p> As you step forward, a gunshot echoes forcing you to take cover. <<if _rand>> <<health `-1*_dmg`>> <br> Too late, the shot dealt <b class='red'>_dmg</b> damage. <</if>> </p> <<a 'Rush in!' key 'n' goto 'Combat'>> <<fight setup.RifleBot>> <</a>>
/* Combat divider */ .divider { display: grid; margin: 2em 0; align-items: center; justify-items: center; } .divider > hr { margin: 0; border: none; height: calc(var(--borderThickness)*1.5); background-color: var(--orange); width: 70%; } .divider > div { position:absolute; color: var(--orange); text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000, -2px 0 0 #000, 2px 0 0 #000, 0 2px 0 #000, 0 -2px 0 #000, 0 0 .1em var(--background), 0 0 .2em var(--background), 0 0 .3em var(--background), 0 0 .4em var(--background); } .divider img { max-height: 3em !important; position: absolute; background-color: var(--background); box-shadow: 0 0 .25em .25em var(--background); } .divCenter { height: 1.5em; width: 1.5em; outline: calc(var(--borderThickness)*1.5) solid var(--orange); transform: rotate(45deg); background-color: var(--background); display: flex; justify-content: center; align-items: center; }
<<adel "What's the key about? Why it is so expensive?">> <<set $netAccess.aware = true>> <<app>> <p class='orange'>What's the key about? Why it is so expensive?</p> <p>This is a network access key.<br> Each one is unique, its encryption is synced so it cannot be copied. Lets you travel freely through the under city. </p> <<a 'Hum, good to know...'>> <<run Dialog.close()>> <</a>> <</adel>>
The heavy metal door opens on the usually bleak labyrinth.